xref: /wlan-driver/qca-wifi-host-cmn/target_if/spectral/target_if_spectral.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) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name  *
5*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for
6*5113495bSYour Name  * any purpose with or without fee is hereby granted, provided that the
7*5113495bSYour Name  * above copyright notice and this permission notice appear in all
8*5113495bSYour Name  * copies.
9*5113495bSYour Name  *
10*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11*5113495bSYour Name  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12*5113495bSYour Name  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13*5113495bSYour Name  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14*5113495bSYour Name  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15*5113495bSYour Name  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16*5113495bSYour Name  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*5113495bSYour Name  * PERFORMANCE OF THIS SOFTWARE.
18*5113495bSYour Name  */
19*5113495bSYour Name 
20*5113495bSYour Name #include <wlan_tgt_def_config.h>
21*5113495bSYour Name #include <hif.h>
22*5113495bSYour Name #include <target_type.h>
23*5113495bSYour Name #include <hif_hw_version.h>
24*5113495bSYour Name #include <wmi_unified_api.h>
25*5113495bSYour Name #include <target_if_spectral.h>
26*5113495bSYour Name #include <wlan_lmac_if_def.h>
27*5113495bSYour Name #include <wlan_osif_priv.h>
28*5113495bSYour Name #include <init_deinit_lmac.h>
29*5113495bSYour Name #include <reg_services_public_struct.h>
30*5113495bSYour Name #include <target_if_spectral_sim.h>
31*5113495bSYour Name #include <target_if.h>
32*5113495bSYour Name #include <qdf_module.h>
33*5113495bSYour Name #include <wlan_reg_services_api.h>
34*5113495bSYour Name #include <wlan_dfs_ucfg_api.h>
35*5113495bSYour Name 
36*5113495bSYour Name /*
37*5113495bSYour Name  * @spectral_ops - Spectral function table, holds the Spectral functions that
38*5113495bSYour Name  * depend on whether the architecture is Direct Attach or Offload. This is used
39*5113495bSYour Name  * to populate the actual Spectral function table present in the Spectral
40*5113495bSYour Name  * module.
41*5113495bSYour Name  */
42*5113495bSYour Name struct target_if_spectral_ops spectral_ops;
43*5113495bSYour Name int spectral_debug_level = DEBUG_SPECTRAL;
44*5113495bSYour Name struct spectral_tgt_ops ops_tgt;
45*5113495bSYour Name 
46*5113495bSYour Name #ifdef SPECTRAL_MODULIZED_ENABLE
47*5113495bSYour Name /**
48*5113495bSYour Name  * target_if_spectral_wmi_service_enabled() - API to check whether a
49*5113495bSYour Name  * given WMI service is enabled
50*5113495bSYour Name  * @psoc: Pointer to psoc
51*5113495bSYour Name  * @wmi_handle: WMI handle
52*5113495bSYour Name  * @service_id: service id
53*5113495bSYour Name  *
54*5113495bSYour Name  * Return: true or false
55*5113495bSYour Name  */
56*5113495bSYour Name static
target_if_spectral_wmi_service_enabled(struct wlan_objmgr_psoc * psoc,wmi_unified_t wmi_handle,uint32_t service_id)57*5113495bSYour Name bool target_if_spectral_wmi_service_enabled(struct wlan_objmgr_psoc *psoc,
58*5113495bSYour Name 					    wmi_unified_t wmi_handle,
59*5113495bSYour Name 					    uint32_t service_id)
60*5113495bSYour Name {
61*5113495bSYour Name 	struct target_if_psoc_spectral *psoc_spectral;
62*5113495bSYour Name 
63*5113495bSYour Name 	if (!psoc) {
64*5113495bSYour Name 		spectral_err("psoc is null");
65*5113495bSYour Name 		return false;
66*5113495bSYour Name 	}
67*5113495bSYour Name 
68*5113495bSYour Name 	if (!wmi_handle) {
69*5113495bSYour Name 		spectral_err("wmi handle is null");
70*5113495bSYour Name 		return false;
71*5113495bSYour Name 	}
72*5113495bSYour Name 
73*5113495bSYour Name 	psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
74*5113495bSYour Name 	if (!psoc_spectral) {
75*5113495bSYour Name 		spectral_err("psoc spectral object is null");
76*5113495bSYour Name 		return false;
77*5113495bSYour Name 	}
78*5113495bSYour Name 
79*5113495bSYour Name 	return psoc_spectral->wmi_ops.wmi_service_enabled(wmi_handle,
80*5113495bSYour Name 							  service_id);
81*5113495bSYour Name }
82*5113495bSYour Name #else
83*5113495bSYour Name /**
84*5113495bSYour Name  * target_if_spectral_wmi_service_enabled() - API to check whether a
85*5113495bSYour Name  * given WMI service is enabled
86*5113495bSYour Name  * @psoc: Pointer to psoc
87*5113495bSYour Name  * @wmi_handle: WMI handle
88*5113495bSYour Name  * @service_id: service id
89*5113495bSYour Name  *
90*5113495bSYour Name  * Return: true or false
91*5113495bSYour Name  */
92*5113495bSYour Name static
target_if_spectral_wmi_service_enabled(struct wlan_objmgr_psoc * psoc,wmi_unified_t wmi_handle,uint32_t service_id)93*5113495bSYour Name bool target_if_spectral_wmi_service_enabled(struct wlan_objmgr_psoc *psoc,
94*5113495bSYour Name 					    wmi_unified_t wmi_handle,
95*5113495bSYour Name 					    uint32_t service_id)
96*5113495bSYour Name {
97*5113495bSYour Name 	return wmi_service_enabled(wmi_handle, service_id);
98*5113495bSYour Name }
99*5113495bSYour Name #endif /* SPECTRAL_MODULIZED_ENABLE */
100*5113495bSYour Name 
get_target_if_spectral_handle_from_pdev(struct wlan_objmgr_pdev * pdev)101*5113495bSYour Name struct target_if_spectral *get_target_if_spectral_handle_from_pdev(
102*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev)
103*5113495bSYour Name {
104*5113495bSYour Name 	struct target_if_spectral *spectral;
105*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
106*5113495bSYour Name 	struct wlan_lmac_if_rx_ops *rx_ops;
107*5113495bSYour Name 
108*5113495bSYour Name 	if (!pdev) {
109*5113495bSYour Name 		spectral_err("pdev is null");
110*5113495bSYour Name 		return NULL;
111*5113495bSYour Name 	}
112*5113495bSYour Name 
113*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
114*5113495bSYour Name 	if (!psoc) {
115*5113495bSYour Name 		spectral_err("psoc is null");
116*5113495bSYour Name 		return NULL;
117*5113495bSYour Name 	}
118*5113495bSYour Name 
119*5113495bSYour Name 	rx_ops = wlan_psoc_get_lmac_if_rxops(psoc);
120*5113495bSYour Name 	if (!rx_ops) {
121*5113495bSYour Name 		spectral_err("rx_ops is null");
122*5113495bSYour Name 		return NULL;
123*5113495bSYour Name 	}
124*5113495bSYour Name 
125*5113495bSYour Name 	spectral = (struct target_if_spectral *)
126*5113495bSYour Name 		rx_ops->sptrl_rx_ops.sptrlro_get_pdev_target_handle(pdev);
127*5113495bSYour Name 
128*5113495bSYour Name 	return spectral;
129*5113495bSYour Name }
130*5113495bSYour Name 
131*5113495bSYour Name qdf_export_symbol(get_target_if_spectral_handle_from_pdev);
132*5113495bSYour Name 
133*5113495bSYour Name /**
134*5113495bSYour Name  * target_if_spectral_get_normal_mode_cap() - API to get normal
135*5113495bSYour Name  * Spectral scan capability of a given pdev
136*5113495bSYour Name  * @pdev: pdev handle
137*5113495bSYour Name  * @normal_mode_disable: Pointer to caller variable
138*5113495bSYour Name  *
139*5113495bSYour Name  * API to get normal Spectral scan mode capability a given pdev.
140*5113495bSYour Name  * This information is derived from the WMI service
141*5113495bSYour Name  * "WMI_SERVICE_SPECTRAL_SCAN_DISABLED".
142*5113495bSYour Name  *
143*5113495bSYour Name  * Return: QDF_STATUS on success
144*5113495bSYour Name  */
145*5113495bSYour Name static QDF_STATUS
target_if_spectral_get_normal_mode_cap(struct wlan_objmgr_pdev * pdev,bool * normal_mode_disable)146*5113495bSYour Name target_if_spectral_get_normal_mode_cap(struct wlan_objmgr_pdev *pdev,
147*5113495bSYour Name 				       bool *normal_mode_disable)
148*5113495bSYour Name {
149*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
150*5113495bSYour Name 	struct wmi_unified *wmi_handle;
151*5113495bSYour Name 	struct target_if_psoc_spectral *psoc_spectral;
152*5113495bSYour Name 
153*5113495bSYour Name 	if (!pdev) {
154*5113495bSYour Name 		spectral_err("pdev is null");
155*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
156*5113495bSYour Name 	}
157*5113495bSYour Name 
158*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
159*5113495bSYour Name 	if (!psoc) {
160*5113495bSYour Name 		spectral_err("psoc is null");
161*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
162*5113495bSYour Name 	}
163*5113495bSYour Name 
164*5113495bSYour Name 	psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
165*5113495bSYour Name 	if (!psoc_spectral) {
166*5113495bSYour Name 		spectral_err("psoc spectral object is null");
167*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
168*5113495bSYour Name 	}
169*5113495bSYour Name 
170*5113495bSYour Name 	wmi_handle =  get_wmi_unified_hdl_from_psoc(psoc);
171*5113495bSYour Name 	if (!wmi_handle) {
172*5113495bSYour Name 		spectral_err("wmi handle is null");
173*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
174*5113495bSYour Name 	}
175*5113495bSYour Name 
176*5113495bSYour Name 	*normal_mode_disable = target_if_spectral_wmi_service_enabled(psoc,
177*5113495bSYour Name 				wmi_handle, wmi_service_spectral_scan_disabled);
178*5113495bSYour Name 
179*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
180*5113495bSYour Name }
181*5113495bSYour Name 
182*5113495bSYour Name /**
183*5113495bSYour Name  * target_if_spectral_get_agile_mode_cap() - API to check agile
184*5113495bSYour Name  * Spectral scan mode capability of a given pdev.
185*5113495bSYour Name  * @pdev: pdev handle
186*5113495bSYour Name  * @agile_cap: Pointer to caller variable
187*5113495bSYour Name  *
188*5113495bSYour Name  * API to check agile Spectral scan mode is disabled for a given pdev.
189*5113495bSYour Name  * This information is derived from the chain mask table entries.
190*5113495bSYour Name  *
191*5113495bSYour Name  * Return: QDF_STATUS on success
192*5113495bSYour Name  */
193*5113495bSYour Name static QDF_STATUS
target_if_spectral_get_agile_mode_cap(struct wlan_objmgr_pdev * pdev,struct target_if_spectral_agile_mode_cap * agile_cap)194*5113495bSYour Name target_if_spectral_get_agile_mode_cap(
195*5113495bSYour Name 			struct wlan_objmgr_pdev *pdev,
196*5113495bSYour Name 			struct target_if_spectral_agile_mode_cap *agile_cap)
197*5113495bSYour Name {
198*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
199*5113495bSYour Name 	struct target_psoc_info *tgt_psoc_info;
200*5113495bSYour Name 	struct wlan_psoc_host_mac_phy_caps *mac_phy_cap_arr;
201*5113495bSYour Name 	struct wlan_psoc_host_mac_phy_caps *mac_phy_cap;
202*5113495bSYour Name 	uint8_t pdev_id, i;
203*5113495bSYour Name 	uint32_t table_id;
204*5113495bSYour Name 	struct wlan_psoc_host_service_ext_param *ext_svc_param;
205*5113495bSYour Name 	struct wlan_psoc_host_chainmask_table *table;
206*5113495bSYour Name 	struct wmi_unified *wmi_handle;
207*5113495bSYour Name 
208*5113495bSYour Name 	if (!pdev) {
209*5113495bSYour Name 		spectral_err("pdev is null");
210*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
211*5113495bSYour Name 	}
212*5113495bSYour Name 
213*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
214*5113495bSYour Name 	if (!psoc) {
215*5113495bSYour Name 		spectral_err("psoc is null");
216*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
217*5113495bSYour Name 	}
218*5113495bSYour Name 
219*5113495bSYour Name 	wmi_handle =  get_wmi_unified_hdl_from_psoc(psoc);
220*5113495bSYour Name 	if (!wmi_handle) {
221*5113495bSYour Name 		spectral_err("wmi handle is null");
222*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
223*5113495bSYour Name 	}
224*5113495bSYour Name 
225*5113495bSYour Name 	/* Agile Spectral is disabled for legacy targets */
226*5113495bSYour Name 	if (!target_if_spectral_wmi_service_enabled(psoc, wmi_handle,
227*5113495bSYour Name 						    wmi_service_ext_msg)) {
228*5113495bSYour Name 		agile_cap->agile_spectral_cap  = false;
229*5113495bSYour Name 		agile_cap->agile_spectral_cap_160 = false;
230*5113495bSYour Name 		agile_cap->agile_spectral_cap_80p80 = false;
231*5113495bSYour Name 		agile_cap->agile_spectral_cap_320 = false;
232*5113495bSYour Name 
233*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
234*5113495bSYour Name 	}
235*5113495bSYour Name 
236*5113495bSYour Name 	tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc);
237*5113495bSYour Name 	if (!tgt_psoc_info) {
238*5113495bSYour Name 		spectral_err("target_psoc_info is null");
239*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
240*5113495bSYour Name 	}
241*5113495bSYour Name 
242*5113495bSYour Name 	mac_phy_cap_arr = target_psoc_get_mac_phy_cap(tgt_psoc_info);
243*5113495bSYour Name 	if (!mac_phy_cap_arr) {
244*5113495bSYour Name 		spectral_err("mac phy cap array is null");
245*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
246*5113495bSYour Name 	}
247*5113495bSYour Name 
248*5113495bSYour Name 	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
249*5113495bSYour Name 	mac_phy_cap = &mac_phy_cap_arr[pdev_id];
250*5113495bSYour Name 	table_id = mac_phy_cap->chainmask_table_id;
251*5113495bSYour Name 	ext_svc_param = target_psoc_get_service_ext_param(tgt_psoc_info);
252*5113495bSYour Name 	if (!ext_svc_param) {
253*5113495bSYour Name 		spectral_err("Extended service ready params null");
254*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
255*5113495bSYour Name 	}
256*5113495bSYour Name 
257*5113495bSYour Name 	table =  &ext_svc_param->chainmask_table[table_id];
258*5113495bSYour Name 
259*5113495bSYour Name 	for (i = 0; i < table->num_valid_chainmasks; i++) {
260*5113495bSYour Name 		agile_cap->agile_spectral_cap |=
261*5113495bSYour Name 			table->cap_list[i].supports_aSpectral;
262*5113495bSYour Name 		agile_cap->agile_spectral_cap_160 |=
263*5113495bSYour Name 			table->cap_list[i].supports_aSpectral_160;
264*5113495bSYour Name 		agile_cap->agile_spectral_cap_320 |= 0;
265*5113495bSYour Name 	}
266*5113495bSYour Name 
267*5113495bSYour Name 	agile_cap->agile_spectral_cap_80p80 = agile_cap->agile_spectral_cap_160;
268*5113495bSYour Name 
269*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
270*5113495bSYour Name }
271*5113495bSYour Name 
272*5113495bSYour Name /**
273*5113495bSYour Name  * target_if_spectral_init_pdev_feature_cap_per_mode() - API to initialize
274*5113495bSYour Name  * Spectral scan pdev feature caps for a given Spectral mode
275*5113495bSYour Name  * @pdev: pdev handle
276*5113495bSYour Name  * @smode: Spectral scan mode
277*5113495bSYour Name  *
278*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE/
279*5113495bSYour Name  * QDF_STATUS_E_INVAL on failure
280*5113495bSYour Name  */
281*5113495bSYour Name static QDF_STATUS
target_if_spectral_init_pdev_feature_cap_per_mode(struct wlan_objmgr_pdev * pdev,enum spectral_scan_mode smode)282*5113495bSYour Name target_if_spectral_init_pdev_feature_cap_per_mode(struct wlan_objmgr_pdev *pdev,
283*5113495bSYour Name 						  enum spectral_scan_mode smode)
284*5113495bSYour Name {
285*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
286*5113495bSYour Name 	bool normal_mode_disable;
287*5113495bSYour Name 	struct target_if_spectral_agile_mode_cap agile_cap = { 0 };
288*5113495bSYour Name 	QDF_STATUS status;
289*5113495bSYour Name 
290*5113495bSYour Name 	if (!pdev) {
291*5113495bSYour Name 		spectral_err("pdev is null");
292*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
293*5113495bSYour Name 	}
294*5113495bSYour Name 
295*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
296*5113495bSYour Name 	if (!psoc) {
297*5113495bSYour Name 		spectral_err("psoc is null");
298*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
299*5113495bSYour Name 	}
300*5113495bSYour Name 
301*5113495bSYour Name 	switch (smode) {
302*5113495bSYour Name 	case SPECTRAL_SCAN_MODE_NORMAL:
303*5113495bSYour Name 		if (target_if_spectral_is_feature_disabled_psoc(psoc)) {
304*5113495bSYour Name 			wlan_pdev_nif_feat_ext_cap_set(
305*5113495bSYour Name 				pdev, WLAN_PDEV_FEXT_NORMAL_SPECTRAL_SCAN_DIS);
306*5113495bSYour Name 
307*5113495bSYour Name 			return QDF_STATUS_SUCCESS;
308*5113495bSYour Name 		}
309*5113495bSYour Name 
310*5113495bSYour Name 		status = target_if_spectral_get_normal_mode_cap(
311*5113495bSYour Name 				pdev, &normal_mode_disable);
312*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
313*5113495bSYour Name 			spectral_err("Failed to get normal spectral scan caps");
314*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
315*5113495bSYour Name 		}
316*5113495bSYour Name 
317*5113495bSYour Name 		if (normal_mode_disable)
318*5113495bSYour Name 			wlan_pdev_nif_feat_ext_cap_set(
319*5113495bSYour Name 				pdev, WLAN_PDEV_FEXT_NORMAL_SPECTRAL_SCAN_DIS);
320*5113495bSYour Name 		else
321*5113495bSYour Name 			wlan_pdev_nif_feat_ext_cap_clear(
322*5113495bSYour Name 				pdev, WLAN_PDEV_FEXT_NORMAL_SPECTRAL_SCAN_DIS);
323*5113495bSYour Name 		break;
324*5113495bSYour Name 
325*5113495bSYour Name 	case SPECTRAL_SCAN_MODE_AGILE:
326*5113495bSYour Name 		if (target_if_spectral_is_feature_disabled_psoc(psoc)) {
327*5113495bSYour Name 			wlan_pdev_nif_feat_ext_cap_set(
328*5113495bSYour Name 			  pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_DIS);
329*5113495bSYour Name 			wlan_pdev_nif_feat_ext_cap_set(
330*5113495bSYour Name 			  pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_160_DIS);
331*5113495bSYour Name 			wlan_pdev_nif_feat_ext_cap_set(
332*5113495bSYour Name 			  pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_80P80_DIS);
333*5113495bSYour Name 			wlan_pdev_nif_feat_ext_cap_set(
334*5113495bSYour Name 			  pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_320_DIS);
335*5113495bSYour Name 
336*5113495bSYour Name 			return QDF_STATUS_SUCCESS;
337*5113495bSYour Name 		}
338*5113495bSYour Name 		status = target_if_spectral_get_agile_mode_cap(
339*5113495bSYour Name 				pdev, &agile_cap);
340*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
341*5113495bSYour Name 			spectral_err("Failed to get agile Spectral capability");
342*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
343*5113495bSYour Name 		}
344*5113495bSYour Name 
345*5113495bSYour Name 		if (!agile_cap.agile_spectral_cap)
346*5113495bSYour Name 			wlan_pdev_nif_feat_ext_cap_set(
347*5113495bSYour Name 			  pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_DIS);
348*5113495bSYour Name 		else
349*5113495bSYour Name 			wlan_pdev_nif_feat_ext_cap_clear(
350*5113495bSYour Name 			  pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_DIS);
351*5113495bSYour Name 
352*5113495bSYour Name 		if (!agile_cap.agile_spectral_cap_160)
353*5113495bSYour Name 			wlan_pdev_nif_feat_ext_cap_set(
354*5113495bSYour Name 			  pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_160_DIS);
355*5113495bSYour Name 		else
356*5113495bSYour Name 			wlan_pdev_nif_feat_ext_cap_clear(
357*5113495bSYour Name 			  pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_160_DIS);
358*5113495bSYour Name 
359*5113495bSYour Name 		if (!agile_cap.agile_spectral_cap_80p80)
360*5113495bSYour Name 			wlan_pdev_nif_feat_ext_cap_set(
361*5113495bSYour Name 			  pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_80P80_DIS);
362*5113495bSYour Name 		else
363*5113495bSYour Name 			wlan_pdev_nif_feat_ext_cap_clear(
364*5113495bSYour Name 			  pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_80P80_DIS);
365*5113495bSYour Name 
366*5113495bSYour Name 		if (!agile_cap.agile_spectral_cap_320)
367*5113495bSYour Name 			wlan_pdev_nif_feat_ext_cap_set(
368*5113495bSYour Name 			  pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_320_DIS);
369*5113495bSYour Name 		else
370*5113495bSYour Name 			wlan_pdev_nif_feat_ext_cap_clear(
371*5113495bSYour Name 			  pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_320_DIS);
372*5113495bSYour Name 
373*5113495bSYour Name 		break;
374*5113495bSYour Name 
375*5113495bSYour Name 	default:
376*5113495bSYour Name 		spectral_err("Invalid Spectral scan mode %d", smode);
377*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
378*5113495bSYour Name 	}
379*5113495bSYour Name 
380*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
381*5113495bSYour Name }
382*5113495bSYour Name 
383*5113495bSYour Name /**
384*5113495bSYour Name  * target_if_spectral_init_pdev_feature_caps() - API to initialize
385*5113495bSYour Name  * Spectral scan pdev feature caps for a given pdev
386*5113495bSYour Name  * @pdev: pdev handle
387*5113495bSYour Name  *
388*5113495bSYour Name  * API initialize normal and agile Spectral scan pdev
389*5113495bSYour Name  * feature caps for a given pdev.
390*5113495bSYour Name  *
391*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_INVAL on failure
392*5113495bSYour Name  */
393*5113495bSYour Name static QDF_STATUS
target_if_spectral_init_pdev_feature_caps(struct wlan_objmgr_pdev * pdev)394*5113495bSYour Name target_if_spectral_init_pdev_feature_caps(struct wlan_objmgr_pdev *pdev)
395*5113495bSYour Name {
396*5113495bSYour Name 	enum spectral_scan_mode smode;
397*5113495bSYour Name 
398*5113495bSYour Name 	if (!pdev) {
399*5113495bSYour Name 		spectral_err("pdev is NULL!");
400*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
401*5113495bSYour Name 	}
402*5113495bSYour Name 
403*5113495bSYour Name 	smode = SPECTRAL_SCAN_MODE_NORMAL;
404*5113495bSYour Name 	for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) {
405*5113495bSYour Name 		QDF_STATUS status;
406*5113495bSYour Name 
407*5113495bSYour Name 		status = target_if_spectral_init_pdev_feature_cap_per_mode(
408*5113495bSYour Name 				pdev, smode);
409*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status))
410*5113495bSYour Name 			return QDF_STATUS_E_INVAL;
411*5113495bSYour Name 	}
412*5113495bSYour Name 
413*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
414*5113495bSYour Name }
415*5113495bSYour Name 
target_if_spectral_get_firstvdev_pdev(struct wlan_objmgr_pdev * pdev,void * obj,void * arg)416*5113495bSYour Name static void target_if_spectral_get_firstvdev_pdev(struct wlan_objmgr_pdev *pdev,
417*5113495bSYour Name 						  void *obj, void *arg)
418*5113495bSYour Name {
419*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev = obj;
420*5113495bSYour Name 	struct wlan_objmgr_vdev **first_vdev = arg;
421*5113495bSYour Name 
422*5113495bSYour Name 	if (!(*first_vdev))
423*5113495bSYour Name 		*first_vdev = vdev;
424*5113495bSYour Name }
425*5113495bSYour Name 
426*5113495bSYour Name struct wlan_objmgr_vdev *
target_if_spectral_get_vdev(struct target_if_spectral * spectral,enum spectral_scan_mode smode)427*5113495bSYour Name target_if_spectral_get_vdev(struct target_if_spectral *spectral,
428*5113495bSYour Name 			    enum spectral_scan_mode smode)
429*5113495bSYour Name {
430*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev = NULL;
431*5113495bSYour Name 	struct wlan_objmgr_vdev *first_vdev = NULL;
432*5113495bSYour Name 
433*5113495bSYour Name 	if (!spectral) {
434*5113495bSYour Name 		spectral_err("spectral variable in null.");
435*5113495bSYour Name 		return NULL;
436*5113495bSYour Name 	}
437*5113495bSYour Name 	pdev = spectral->pdev_obj;
438*5113495bSYour Name 	if (!pdev) {
439*5113495bSYour Name 		spectral_err("pdev variable in null.");
440*5113495bSYour Name 		return NULL;
441*5113495bSYour Name 	}
442*5113495bSYour Name 
443*5113495bSYour Name 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
444*5113495bSYour Name 		spectral_err("Invalid Spectral mode %u", smode);
445*5113495bSYour Name 		return NULL;
446*5113495bSYour Name 	}
447*5113495bSYour Name 
448*5113495bSYour Name 	if (spectral->vdev_id[smode] != WLAN_INVALID_VDEV_ID) {
449*5113495bSYour Name 		first_vdev = wlan_objmgr_get_vdev_by_id_from_pdev(
450*5113495bSYour Name 						pdev, spectral->vdev_id[smode],
451*5113495bSYour Name 						WLAN_SPECTRAL_ID);
452*5113495bSYour Name 		return first_vdev;
453*5113495bSYour Name 	}
454*5113495bSYour Name 
455*5113495bSYour Name 	if (wlan_objmgr_pdev_try_get_ref(pdev, WLAN_SPECTRAL_ID) !=
456*5113495bSYour Name 	    QDF_STATUS_SUCCESS) {
457*5113495bSYour Name 		spectral_err("Unable to get pdev reference.");
458*5113495bSYour Name 		return NULL;
459*5113495bSYour Name 	}
460*5113495bSYour Name 
461*5113495bSYour Name 	wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
462*5113495bSYour Name 					  target_if_spectral_get_firstvdev_pdev,
463*5113495bSYour Name 					  &first_vdev, 0, WLAN_SPECTRAL_ID);
464*5113495bSYour Name 
465*5113495bSYour Name 	wlan_objmgr_pdev_release_ref(pdev, WLAN_SPECTRAL_ID);
466*5113495bSYour Name 
467*5113495bSYour Name 	if (!first_vdev)
468*5113495bSYour Name 		return NULL;
469*5113495bSYour Name 
470*5113495bSYour Name 	if (wlan_objmgr_vdev_try_get_ref(first_vdev, WLAN_SPECTRAL_ID) !=
471*5113495bSYour Name 			QDF_STATUS_SUCCESS)
472*5113495bSYour Name 		first_vdev = NULL;
473*5113495bSYour Name 
474*5113495bSYour Name 	return first_vdev;
475*5113495bSYour Name }
476*5113495bSYour Name 
477*5113495bSYour Name /**
478*5113495bSYour Name  * target_if_send_vdev_spectral_configure_cmd() - Send WMI command to configure
479*5113495bSYour Name  * spectral parameters
480*5113495bSYour Name  * @spectral: Pointer to Spectral target_if internal private data
481*5113495bSYour Name  * @smode: Spectral scan mode
482*5113495bSYour Name  * @param: Pointer to spectral_config giving the Spectral configuration
483*5113495bSYour Name  *
484*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS on success, negative error code on failure
485*5113495bSYour Name  */
486*5113495bSYour Name static int
target_if_send_vdev_spectral_configure_cmd(struct target_if_spectral * spectral,enum spectral_scan_mode smode,struct spectral_config * param)487*5113495bSYour Name target_if_send_vdev_spectral_configure_cmd(struct target_if_spectral *spectral,
488*5113495bSYour Name 					   enum spectral_scan_mode smode,
489*5113495bSYour Name 					   struct spectral_config *param)
490*5113495bSYour Name {
491*5113495bSYour Name 	struct vdev_spectral_configure_params sparam;
492*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
493*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev = NULL;
494*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev = NULL;
495*5113495bSYour Name 	struct target_if_psoc_spectral *psoc_spectral;
496*5113495bSYour Name 
497*5113495bSYour Name 	if (!spectral || !param || !(spectral->pdev_obj)) {
498*5113495bSYour Name 		spectral_err("null params: spectral %pK, spectral_config %pK, pdev: %pK.",
499*5113495bSYour Name 			     spectral, param, pdev);
500*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_NULL_VALUE);
501*5113495bSYour Name 	}
502*5113495bSYour Name 
503*5113495bSYour Name 	pdev = spectral->pdev_obj;
504*5113495bSYour Name 
505*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
506*5113495bSYour Name 	if (!psoc) {
507*5113495bSYour Name 		spectral_err("psoc is null");
508*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
509*5113495bSYour Name 	}
510*5113495bSYour Name 
511*5113495bSYour Name 	psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
512*5113495bSYour Name 	if (!psoc_spectral) {
513*5113495bSYour Name 		spectral_err("psoc spectral object is null");
514*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
515*5113495bSYour Name 	}
516*5113495bSYour Name 
517*5113495bSYour Name 	vdev = target_if_spectral_get_vdev(spectral, smode);
518*5113495bSYour Name 	if (!vdev)
519*5113495bSYour Name 		return QDF_STATUS_E_NOENT;
520*5113495bSYour Name 
521*5113495bSYour Name 	qdf_mem_zero(&sparam, sizeof(sparam));
522*5113495bSYour Name 
523*5113495bSYour Name 	sparam.vdev_id = wlan_vdev_get_id(vdev);
524*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
525*5113495bSYour Name 
526*5113495bSYour Name 	sparam.count = param->ss_count;
527*5113495bSYour Name 	sparam.period = param->ss_period;
528*5113495bSYour Name 	sparam.fft_recap = param->ss_recapture;
529*5113495bSYour Name 	sparam.spectral_pri = param->ss_spectral_pri;
530*5113495bSYour Name 	sparam.fft_size = param->ss_fft_size;
531*5113495bSYour Name 	sparam.gc_enable = param->ss_gc_ena;
532*5113495bSYour Name 	sparam.restart_enable = param->ss_restart_ena;
533*5113495bSYour Name 	sparam.noise_floor_ref = param->ss_noise_floor_ref;
534*5113495bSYour Name 	sparam.init_delay = param->ss_init_delay;
535*5113495bSYour Name 	sparam.nb_tone_thr = param->ss_nb_tone_thr;
536*5113495bSYour Name 	sparam.str_bin_thr = param->ss_str_bin_thr;
537*5113495bSYour Name 	sparam.wb_rpt_mode = param->ss_wb_rpt_mode;
538*5113495bSYour Name 	sparam.rssi_rpt_mode = param->ss_rssi_rpt_mode;
539*5113495bSYour Name 	sparam.rssi_thr = param->ss_rssi_thr;
540*5113495bSYour Name 	sparam.pwr_format = param->ss_pwr_format;
541*5113495bSYour Name 	sparam.rpt_mode = param->ss_rpt_mode;
542*5113495bSYour Name 	sparam.bin_scale = param->ss_bin_scale;
543*5113495bSYour Name 	sparam.dbm_adj = param->ss_dbm_adj;
544*5113495bSYour Name 	sparam.chn_mask = param->ss_chn_mask;
545*5113495bSYour Name 	sparam.mode = smode;
546*5113495bSYour Name 	sparam.center_freq1 = param->ss_frequency.cfreq1;
547*5113495bSYour Name 	sparam.center_freq2 = param->ss_frequency.cfreq2;
548*5113495bSYour Name 	sparam.chan_width = param->ss_bandwidth;
549*5113495bSYour Name 
550*5113495bSYour Name 	return psoc_spectral->wmi_ops.wmi_spectral_configure_cmd_send(
551*5113495bSYour Name 				GET_WMI_HDL_FROM_PDEV(pdev), &sparam);
552*5113495bSYour Name }
553*5113495bSYour Name 
554*5113495bSYour Name /**
555*5113495bSYour Name  * target_if_send_vdev_spectral_enable_cmd() - Send WMI command to
556*5113495bSYour Name  * enable/disable Spectral
557*5113495bSYour Name  * @spectral: Pointer to Spectral target_if internal private data
558*5113495bSYour Name  * @smode: Spectral scan mode
559*5113495bSYour Name  * @is_spectral_active_valid: Flag to indicate if spectral activate (trigger) is
560*5113495bSYour Name  * valid
561*5113495bSYour Name  * @is_spectral_active: Value of spectral activate
562*5113495bSYour Name  * @is_spectral_enabled_valid: Flag to indicate if spectral enable is valid
563*5113495bSYour Name  * @is_spectral_enabled: Value of spectral enable
564*5113495bSYour Name  *
565*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS on success, negative error code on failure
566*5113495bSYour Name  */
567*5113495bSYour Name static int
target_if_send_vdev_spectral_enable_cmd(struct target_if_spectral * spectral,enum spectral_scan_mode smode,uint8_t is_spectral_active_valid,uint8_t is_spectral_active,uint8_t is_spectral_enabled_valid,uint8_t is_spectral_enabled)568*5113495bSYour Name target_if_send_vdev_spectral_enable_cmd(struct target_if_spectral *spectral,
569*5113495bSYour Name 					enum spectral_scan_mode smode,
570*5113495bSYour Name 					uint8_t is_spectral_active_valid,
571*5113495bSYour Name 					uint8_t is_spectral_active,
572*5113495bSYour Name 					uint8_t is_spectral_enabled_valid,
573*5113495bSYour Name 					uint8_t is_spectral_enabled)
574*5113495bSYour Name {
575*5113495bSYour Name 	struct vdev_spectral_enable_params param;
576*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
577*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev = NULL;
578*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev = NULL;
579*5113495bSYour Name 	struct target_if_psoc_spectral *psoc_spectral;
580*5113495bSYour Name 
581*5113495bSYour Name 	if (!spectral) {
582*5113495bSYour Name 		spectral_err("spectral is null");
583*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_NULL_VALUE);
584*5113495bSYour Name 	}
585*5113495bSYour Name 
586*5113495bSYour Name 	pdev = spectral->pdev_obj;
587*5113495bSYour Name 
588*5113495bSYour Name 	if (!pdev) {
589*5113495bSYour Name 		spectral_err("pdev is null");
590*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_NULL_VALUE);
591*5113495bSYour Name 	}
592*5113495bSYour Name 
593*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
594*5113495bSYour Name 	if (!psoc) {
595*5113495bSYour Name 		spectral_err("psoc is null");
596*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
597*5113495bSYour Name 	}
598*5113495bSYour Name 
599*5113495bSYour Name 	psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
600*5113495bSYour Name 	if (!psoc_spectral) {
601*5113495bSYour Name 		spectral_err("psoc spectral object is null");
602*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
603*5113495bSYour Name 	}
604*5113495bSYour Name 
605*5113495bSYour Name 	vdev = target_if_spectral_get_vdev(spectral, smode);
606*5113495bSYour Name 	if (!vdev)
607*5113495bSYour Name 		return QDF_STATUS_E_NOENT;
608*5113495bSYour Name 
609*5113495bSYour Name 	qdf_mem_zero(&param, sizeof(param));
610*5113495bSYour Name 
611*5113495bSYour Name 	param.vdev_id = wlan_vdev_get_id(vdev);
612*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
613*5113495bSYour Name 
614*5113495bSYour Name 	param.active_valid = is_spectral_active_valid;
615*5113495bSYour Name 	param.enabled_valid = is_spectral_enabled_valid;
616*5113495bSYour Name 	param.active = is_spectral_active;
617*5113495bSYour Name 	param.enabled = is_spectral_enabled;
618*5113495bSYour Name 	param.mode = smode;
619*5113495bSYour Name 
620*5113495bSYour Name 	return psoc_spectral->wmi_ops.wmi_spectral_enable_cmd_send(
621*5113495bSYour Name 				GET_WMI_HDL_FROM_PDEV(pdev), &param);
622*5113495bSYour Name }
623*5113495bSYour Name 
624*5113495bSYour Name /**
625*5113495bSYour Name  * is_spectral_arch_beryllium() - Check whether the given target Spectral
626*5113495bSYour Name  * architecture is Beryllium
627*5113495bSYour Name  * @target_tpe: Target type
628*5113495bSYour Name  *
629*5113495bSYour Name  * Return: true if the spectral architecture is Beryllium, else false
630*5113495bSYour Name  */
is_spectral_arch_beryllium(uint32_t target_tpe)631*5113495bSYour Name static inline bool is_spectral_arch_beryllium(uint32_t target_tpe)
632*5113495bSYour Name {
633*5113495bSYour Name 	if ((target_tpe == TARGET_TYPE_QCN9224) ||
634*5113495bSYour Name 	    (target_tpe == TARGET_TYPE_QCA5332) ||
635*5113495bSYour Name 	    (target_tpe == TARGET_TYPE_QCN6432))
636*5113495bSYour Name 		return true;
637*5113495bSYour Name 
638*5113495bSYour Name 	return false;
639*5113495bSYour Name }
640*5113495bSYour Name 
641*5113495bSYour Name /*
642*5113495bSYour Name  * List of supported sscan BWs. Make sure to maintain the array elements in the
643*5113495bSYour Name  * same order of BWs as that of struct spectral_supported_bws bitmap.
644*5113495bSYour Name  */
645*5113495bSYour Name static const enum phy_ch_width supported_sscan_bw_list[] = {
646*5113495bSYour Name 	CH_WIDTH_5MHZ,
647*5113495bSYour Name 	CH_WIDTH_10MHZ,
648*5113495bSYour Name 	CH_WIDTH_20MHZ,
649*5113495bSYour Name 	CH_WIDTH_40MHZ,
650*5113495bSYour Name 	CH_WIDTH_80MHZ,
651*5113495bSYour Name 	CH_WIDTH_160MHZ,
652*5113495bSYour Name 	CH_WIDTH_80P80MHZ,
653*5113495bSYour Name #ifdef WLAN_FEATURE_11BE
654*5113495bSYour Name 	CH_WIDTH_320MHZ,
655*5113495bSYour Name #endif
656*5113495bSYour Name };
657*5113495bSYour Name 
658*5113495bSYour Name #define INVALID_SSCAN_BW_POS (-1)
get_supported_sscan_bw_pos(enum phy_ch_width sscan_bw)659*5113495bSYour Name int get_supported_sscan_bw_pos(enum phy_ch_width sscan_bw)
660*5113495bSYour Name {
661*5113495bSYour Name 	int max_pos, pos;
662*5113495bSYour Name 
663*5113495bSYour Name 	max_pos =  QDF_ARRAY_SIZE(supported_sscan_bw_list);
664*5113495bSYour Name 	for (pos = 0; pos < max_pos; pos++) {
665*5113495bSYour Name 		if (supported_sscan_bw_list[pos] == sscan_bw)
666*5113495bSYour Name 			return pos;
667*5113495bSYour Name 	}
668*5113495bSYour Name 
669*5113495bSYour Name 	return INVALID_SSCAN_BW_POS;
670*5113495bSYour Name }
671*5113495bSYour Name 
672*5113495bSYour Name /**
673*5113495bSYour Name  * target_if_is_sscan_bw_supported() - Check whether the given sscan_bw is
674*5113495bSYour Name  * supported
675*5113495bSYour Name  * @spectral: Spectral LMAC object
676*5113495bSYour Name  * @smode: Spectral scan mode
677*5113495bSYour Name  * @sscan_bw: Spectral scan bandwidth
678*5113495bSYour Name  * @op_bw: operating bandwidth
679*5113495bSYour Name  * @is_bw_supported: Pointer to the caller variable where this function
680*5113495bSYour Name  * populates whether @sscan_bw is supported
681*5113495bSYour Name  * @is_80_80_agile: Indicates an 80+80 agile Scan request
682*5113495bSYour Name  *
683*5113495bSYour Name  * Return: QDF_STATUS of operation
684*5113495bSYour Name  */
685*5113495bSYour Name static QDF_STATUS
target_if_is_sscan_bw_supported(struct target_if_spectral * spectral,enum spectral_scan_mode smode,enum phy_ch_width sscan_bw,enum phy_ch_width op_bw,bool * is_bw_supported,bool is_80_80_agile)686*5113495bSYour Name target_if_is_sscan_bw_supported(struct target_if_spectral *spectral,
687*5113495bSYour Name 				enum spectral_scan_mode smode,
688*5113495bSYour Name 				enum phy_ch_width sscan_bw,
689*5113495bSYour Name 				enum phy_ch_width op_bw,
690*5113495bSYour Name 				bool *is_bw_supported,
691*5113495bSYour Name 				bool is_80_80_agile)
692*5113495bSYour Name {
693*5113495bSYour Name 	struct spectral_supported_bws *supported_bws;
694*5113495bSYour Name 
695*5113495bSYour Name 	*is_bw_supported = false;
696*5113495bSYour Name 
697*5113495bSYour Name 	if (op_bw >= CH_WIDTH_INVALID) {
698*5113495bSYour Name 		spectral_err("Invalid channel width %d", op_bw);
699*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
700*5113495bSYour Name 	}
701*5113495bSYour Name 
702*5113495bSYour Name 	if ((is_80_80_agile && sscan_bw != CH_WIDTH_80P80MHZ) ||
703*5113495bSYour Name 	    (!is_80_80_agile && sscan_bw == CH_WIDTH_80P80MHZ)) {
704*5113495bSYour Name 		*is_bw_supported = false;
705*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
706*5113495bSYour Name 	}
707*5113495bSYour Name 
708*5113495bSYour Name 	/* Get the supported sscan bandwidths for this operating bandwidth */
709*5113495bSYour Name 	supported_bws = &spectral->supported_bws[smode][op_bw];
710*5113495bSYour Name 	*is_bw_supported = supported_bws->bandwidths &
711*5113495bSYour Name 				(1 << get_supported_sscan_bw_pos(sscan_bw));
712*5113495bSYour Name 
713*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
714*5113495bSYour Name }
715*5113495bSYour Name 
716*5113495bSYour Name /**
717*5113495bSYour Name  * get_max_sscan_bw() - Get the maximum sscan bandwidth for a given operating
718*5113495bSYour Name  * bandwidth
719*5113495bSYour Name  * @spectral: Spectral LMAC object
720*5113495bSYour Name  * @smode: Spectral scan mode
721*5113495bSYour Name  * @op_bw: operating bandwidth
722*5113495bSYour Name  *
723*5113495bSYour Name  * Return: Maximum sscan bandwidth for @op_bw on success, else CH_WIDTH_INVALID
724*5113495bSYour Name  */
725*5113495bSYour Name static enum phy_ch_width
get_max_sscan_bw(struct target_if_spectral * spectral,enum spectral_scan_mode smode,enum phy_ch_width op_bw)726*5113495bSYour Name get_max_sscan_bw(struct target_if_spectral *spectral,
727*5113495bSYour Name 		 enum spectral_scan_mode smode,
728*5113495bSYour Name 		 enum phy_ch_width op_bw)
729*5113495bSYour Name {
730*5113495bSYour Name 	int op_bw_pos, pos;
731*5113495bSYour Name 	struct spectral_supported_bws *supported_bws;
732*5113495bSYour Name 
733*5113495bSYour Name 	supported_bws = &spectral->supported_bws[smode][op_bw];
734*5113495bSYour Name 	op_bw_pos = get_supported_sscan_bw_pos(op_bw);
735*5113495bSYour Name 
736*5113495bSYour Name 	/**
737*5113495bSYour Name 	 * Start with operating bandwidth, and keep reducing the bandwidth until
738*5113495bSYour Name 	 * a supported sscan BW is found.
739*5113495bSYour Name 	 */
740*5113495bSYour Name 	for (pos = op_bw_pos; pos >= 0; pos--) {
741*5113495bSYour Name 		if (supported_bws->bandwidths & (1 << pos))
742*5113495bSYour Name 			return supported_sscan_bw_list[pos];
743*5113495bSYour Name 	}
744*5113495bSYour Name 
745*5113495bSYour Name 	return CH_WIDTH_INVALID;
746*5113495bSYour Name }
747*5113495bSYour Name 
748*5113495bSYour Name /* target_if_spectral_find_agile_width() - Given a channel width enum, find the
749*5113495bSYour Name  * corresponding translation for Agile channel width.
750*5113495bSYour Name  * @spectral: pointer to Spectral object
751*5113495bSYour Name  * @op_width: operating channel width
752*5113495bSYour Name  * @is_80_80_agile: Indicates an 80+80 agile Scan request
753*5113495bSYour Name  *
754*5113495bSYour Name  * Return: The translated channel width enum.
755*5113495bSYour Name  */
756*5113495bSYour Name static enum phy_ch_width
target_if_spectral_find_agile_width(struct target_if_spectral * spectral,enum phy_ch_width op_bw,bool is_80_80_agile)757*5113495bSYour Name target_if_spectral_find_agile_width(struct target_if_spectral *spectral,
758*5113495bSYour Name 				    enum phy_ch_width op_bw,
759*5113495bSYour Name 				    bool is_80_80_agile)
760*5113495bSYour Name {
761*5113495bSYour Name 	enum phy_ch_width agile_width;
762*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev;
763*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
764*5113495bSYour Name 
765*5113495bSYour Name 	if (!spectral) {
766*5113495bSYour Name 		spectral_err("Spectral object is null");
767*5113495bSYour Name 		return CH_WIDTH_INVALID;
768*5113495bSYour Name 	}
769*5113495bSYour Name 
770*5113495bSYour Name 	pdev =  spectral->pdev_obj;
771*5113495bSYour Name 	if (!pdev) {
772*5113495bSYour Name 		spectral_err("pdev is null");
773*5113495bSYour Name 		return CH_WIDTH_INVALID;
774*5113495bSYour Name 	}
775*5113495bSYour Name 
776*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
777*5113495bSYour Name 	if (!psoc) {
778*5113495bSYour Name 		spectral_err("psoc is null");
779*5113495bSYour Name 		return CH_WIDTH_INVALID;
780*5113495bSYour Name 	}
781*5113495bSYour Name 
782*5113495bSYour Name 	agile_width = get_max_sscan_bw(spectral, SPECTRAL_SCAN_MODE_AGILE,
783*5113495bSYour Name 				       op_bw);
784*5113495bSYour Name 
785*5113495bSYour Name 	if (wlan_psoc_nif_fw_ext_cap_get(psoc,
786*5113495bSYour Name 					 WLAN_SOC_RESTRICTED_80P80_SUPPORT)) {
787*5113495bSYour Name 		switch (op_bw) {
788*5113495bSYour Name 		case CH_WIDTH_80P80MHZ:
789*5113495bSYour Name 			if (!is_80_80_agile)
790*5113495bSYour Name 				agile_width = CH_WIDTH_160MHZ;
791*5113495bSYour Name 			else
792*5113495bSYour Name 				agile_width = CH_WIDTH_80P80MHZ;
793*5113495bSYour Name 
794*5113495bSYour Name 			break;
795*5113495bSYour Name 
796*5113495bSYour Name 		case CH_WIDTH_160MHZ:
797*5113495bSYour Name 			if (is_80_80_agile)
798*5113495bSYour Name 				agile_width = CH_WIDTH_80P80MHZ;
799*5113495bSYour Name 			else
800*5113495bSYour Name 				agile_width = CH_WIDTH_160MHZ;
801*5113495bSYour Name 
802*5113495bSYour Name 			break;
803*5113495bSYour Name 
804*5113495bSYour Name 		default:
805*5113495bSYour Name 			break;
806*5113495bSYour Name 		}
807*5113495bSYour Name 	}
808*5113495bSYour Name 
809*5113495bSYour Name 	return agile_width;
810*5113495bSYour Name }
811*5113495bSYour Name 
812*5113495bSYour Name /**
813*5113495bSYour Name  * get_default_sscan_bw() - Get the default sscan bandwidth for a given
814*5113495bSYour Name  * operating bandwidth
815*5113495bSYour Name  * @spectral: Spectral LMAC object
816*5113495bSYour Name  * @smode: Spectral scan mode
817*5113495bSYour Name  * @is_80_80_agile: Indicates an 80+80 agile Scan request
818*5113495bSYour Name  *
819*5113495bSYour Name  * Return: Default sscan bandwidth for @op_bw on success, else CH_WIDTH_INVALID
820*5113495bSYour Name  */
821*5113495bSYour Name static enum phy_ch_width
get_default_sscan_bw(struct target_if_spectral * spectral,enum spectral_scan_mode smode,bool is_80_80_agile)822*5113495bSYour Name get_default_sscan_bw(struct target_if_spectral *spectral,
823*5113495bSYour Name 		     enum spectral_scan_mode smode,
824*5113495bSYour Name 		     bool is_80_80_agile)
825*5113495bSYour Name {
826*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
827*5113495bSYour Name 	enum phy_ch_width vdev_ch_width, sscan_width;
828*5113495bSYour Name 
829*5113495bSYour Name 	vdev = target_if_spectral_get_vdev(spectral, smode);
830*5113495bSYour Name 	if (!vdev) {
831*5113495bSYour Name 		spectral_err("vdev is null");
832*5113495bSYour Name 		return CH_WIDTH_INVALID;
833*5113495bSYour Name 	}
834*5113495bSYour Name 
835*5113495bSYour Name 	vdev_ch_width = target_if_vdev_get_ch_width(vdev);
836*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
837*5113495bSYour Name 	if (vdev_ch_width >= CH_WIDTH_INVALID) {
838*5113495bSYour Name 		spectral_err("Invalid vdev channel width %d", vdev_ch_width);
839*5113495bSYour Name 		return CH_WIDTH_INVALID;
840*5113495bSYour Name 	}
841*5113495bSYour Name 
842*5113495bSYour Name 	switch (smode) {
843*5113495bSYour Name 	case SPECTRAL_SCAN_MODE_NORMAL:
844*5113495bSYour Name 		sscan_width = get_max_sscan_bw(spectral, smode, vdev_ch_width);
845*5113495bSYour Name 		break;
846*5113495bSYour Name 
847*5113495bSYour Name 	case SPECTRAL_SCAN_MODE_AGILE:
848*5113495bSYour Name 		sscan_width = target_if_spectral_find_agile_width(
849*5113495bSYour Name 				spectral, vdev_ch_width, is_80_80_agile);
850*5113495bSYour Name 		break;
851*5113495bSYour Name 
852*5113495bSYour Name 	default:
853*5113495bSYour Name 		sscan_width = CH_WIDTH_INVALID;
854*5113495bSYour Name 		break;
855*5113495bSYour Name 	}
856*5113495bSYour Name 
857*5113495bSYour Name 	return sscan_width;
858*5113495bSYour Name }
859*5113495bSYour Name 
860*5113495bSYour Name /**
861*5113495bSYour Name  * target_if_spectral_info_init_defaults() - Helper function to load defaults
862*5113495bSYour Name  * for Spectral information (parameters and state) into cache.
863*5113495bSYour Name  * @spectral: Pointer to Spectral target_if internal private data
864*5113495bSYour Name  * @smode: Spectral scan mode
865*5113495bSYour Name  *
866*5113495bSYour Name  * It is assumed that the caller has obtained the requisite lock if applicable.
867*5113495bSYour Name  * Note that this is currently treated as a temporary function.  Ideally, we
868*5113495bSYour Name  * would like to get defaults from the firmware.
869*5113495bSYour Name  *
870*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
871*5113495bSYour Name  */
872*5113495bSYour Name static QDF_STATUS
target_if_spectral_info_init_defaults(struct target_if_spectral * spectral,enum spectral_scan_mode smode)873*5113495bSYour Name target_if_spectral_info_init_defaults(struct target_if_spectral *spectral,
874*5113495bSYour Name 				      enum spectral_scan_mode smode)
875*5113495bSYour Name {
876*5113495bSYour Name 	struct target_if_spectral_param_state_info *info;
877*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev = NULL;
878*5113495bSYour Name 	enum phy_ch_width sscan_bw;
879*5113495bSYour Name 
880*5113495bSYour Name 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
881*5113495bSYour Name 		spectral_err("Invalid Spectral mode %u", smode);
882*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
883*5113495bSYour Name 	}
884*5113495bSYour Name 
885*5113495bSYour Name 	info = &spectral->param_info[smode];
886*5113495bSYour Name 
887*5113495bSYour Name 	/* State */
888*5113495bSYour Name 	info->osps_cache.osc_spectral_active = SPECTRAL_SCAN_ACTIVE_DEFAULT;
889*5113495bSYour Name 
890*5113495bSYour Name 	info->osps_cache.osc_spectral_enabled = SPECTRAL_SCAN_ENABLE_DEFAULT;
891*5113495bSYour Name 
892*5113495bSYour Name 	/* Parameters */
893*5113495bSYour Name 	info->osps_cache.osc_params.ss_count = SPECTRAL_SCAN_COUNT_DEFAULT;
894*5113495bSYour Name 
895*5113495bSYour Name 	if (spectral->spectral_gen == SPECTRAL_GEN3)
896*5113495bSYour Name 		info->osps_cache.osc_params.ss_period =
897*5113495bSYour Name 			SPECTRAL_SCAN_PERIOD_GEN_III_DEFAULT;
898*5113495bSYour Name 	else
899*5113495bSYour Name 		info->osps_cache.osc_params.ss_period =
900*5113495bSYour Name 			SPECTRAL_SCAN_PERIOD_GEN_II_DEFAULT;
901*5113495bSYour Name 
902*5113495bSYour Name 	info->osps_cache.osc_params.ss_recapture =
903*5113495bSYour Name 				SPECTRAL_FFT_RECAPTURE_DEFAULT;
904*5113495bSYour Name 	info->osps_cache.osc_params.ss_spectral_pri =
905*5113495bSYour Name 	    SPECTRAL_SCAN_PRIORITY_DEFAULT;
906*5113495bSYour Name 
907*5113495bSYour Name 	info->osps_cache.osc_params.ss_fft_size =
908*5113495bSYour Name 	    SPECTRAL_SCAN_FFT_SIZE_DEFAULT;
909*5113495bSYour Name 
910*5113495bSYour Name 	info->osps_cache.osc_params.ss_gc_ena = SPECTRAL_SCAN_GC_ENA_DEFAULT;
911*5113495bSYour Name 
912*5113495bSYour Name 	info->osps_cache.osc_params.ss_restart_ena =
913*5113495bSYour Name 	    SPECTRAL_SCAN_RESTART_ENA_DEFAULT;
914*5113495bSYour Name 
915*5113495bSYour Name 	info->osps_cache.osc_params.ss_noise_floor_ref =
916*5113495bSYour Name 	    SPECTRAL_SCAN_NOISE_FLOOR_REF_DEFAULT;
917*5113495bSYour Name 
918*5113495bSYour Name 	info->osps_cache.osc_params.ss_init_delay =
919*5113495bSYour Name 	    SPECTRAL_SCAN_INIT_DELAY_DEFAULT;
920*5113495bSYour Name 
921*5113495bSYour Name 	info->osps_cache.osc_params.ss_nb_tone_thr =
922*5113495bSYour Name 	    SPECTRAL_SCAN_NB_TONE_THR_DEFAULT;
923*5113495bSYour Name 
924*5113495bSYour Name 	info->osps_cache.osc_params.ss_str_bin_thr =
925*5113495bSYour Name 	    SPECTRAL_SCAN_STR_BIN_THR_DEFAULT;
926*5113495bSYour Name 
927*5113495bSYour Name 	info->osps_cache.osc_params.ss_wb_rpt_mode =
928*5113495bSYour Name 	    SPECTRAL_SCAN_WB_RPT_MODE_DEFAULT;
929*5113495bSYour Name 
930*5113495bSYour Name 	info->osps_cache.osc_params.ss_rssi_rpt_mode =
931*5113495bSYour Name 	    SPECTRAL_SCAN_RSSI_RPT_MODE_DEFAULT;
932*5113495bSYour Name 
933*5113495bSYour Name 	info->osps_cache.osc_params.ss_rssi_thr =
934*5113495bSYour Name 	    SPECTRAL_SCAN_RSSI_THR_DEFAULT;
935*5113495bSYour Name 
936*5113495bSYour Name 	info->osps_cache.osc_params.ss_pwr_format =
937*5113495bSYour Name 	    SPECTRAL_SCAN_PWR_FORMAT_DEFAULT;
938*5113495bSYour Name 
939*5113495bSYour Name 	info->osps_cache.osc_params.ss_rpt_mode =
940*5113495bSYour Name 	    SPECTRAL_SCAN_RPT_MODE_DEFAULT;
941*5113495bSYour Name 
942*5113495bSYour Name 	info->osps_cache.osc_params.ss_bin_scale =
943*5113495bSYour Name 	    SPECTRAL_SCAN_BIN_SCALE_DEFAULT;
944*5113495bSYour Name 
945*5113495bSYour Name 	info->osps_cache.osc_params.ss_dbm_adj = SPECTRAL_SCAN_DBM_ADJ_DEFAULT;
946*5113495bSYour Name 
947*5113495bSYour Name 	vdev = target_if_spectral_get_vdev(spectral, smode);
948*5113495bSYour Name 	if (!vdev)
949*5113495bSYour Name 		return QDF_STATUS_E_NOENT;
950*5113495bSYour Name 
951*5113495bSYour Name 	info->osps_cache.osc_params.ss_chn_mask =
952*5113495bSYour Name 	    wlan_vdev_mlme_get_rxchainmask(vdev);
953*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
954*5113495bSYour Name 
955*5113495bSYour Name 	info->osps_cache.osc_params.ss_short_report =
956*5113495bSYour Name 		SPECTRAL_SCAN_SHORT_REPORT_DEFAULT;
957*5113495bSYour Name 
958*5113495bSYour Name 	info->osps_cache.osc_params.ss_fft_period =
959*5113495bSYour Name 		SPECTRAL_SCAN_FFT_PERIOD_DEFAULT;
960*5113495bSYour Name 
961*5113495bSYour Name 	info->osps_cache.osc_params.ss_frequency.cfreq1 =
962*5113495bSYour Name 		SPECTRAL_SCAN_FREQUENCY_DEFAULT;
963*5113495bSYour Name 	info->osps_cache.osc_params.ss_frequency.cfreq2 =
964*5113495bSYour Name 		SPECTRAL_SCAN_FREQUENCY_DEFAULT;
965*5113495bSYour Name 
966*5113495bSYour Name 	sscan_bw = get_default_sscan_bw(spectral, smode, false);
967*5113495bSYour Name 	if (sscan_bw >= CH_WIDTH_INVALID) {
968*5113495bSYour Name 		spectral_err("Invalid sscan BW %u", sscan_bw);
969*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
970*5113495bSYour Name 	}
971*5113495bSYour Name 	info->osps_cache.osc_params.ss_bandwidth = sscan_bw;
972*5113495bSYour Name 
973*5113495bSYour Name 	/* The cache is now valid */
974*5113495bSYour Name 	info->osps_cache.osc_is_valid = 1;
975*5113495bSYour Name 
976*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
977*5113495bSYour Name }
978*5113495bSYour Name 
979*5113495bSYour Name /**
980*5113495bSYour Name  * target_if_log_read_spectral_active() - Helper function to log whether
981*5113495bSYour Name  * spectral is active after reading cache
982*5113495bSYour Name  * @function_name: Function name
983*5113495bSYour Name  * @output: whether spectral is active or not
984*5113495bSYour Name  *
985*5113495bSYour Name  * Helper function to log whether spectral is active after reading cache
986*5113495bSYour Name  *
987*5113495bSYour Name  * Return: none
988*5113495bSYour Name  */
989*5113495bSYour Name static void
target_if_log_read_spectral_active(const char * function_name,unsigned char output)990*5113495bSYour Name target_if_log_read_spectral_active(
991*5113495bSYour Name 	const char *function_name,
992*5113495bSYour Name 	unsigned char output)
993*5113495bSYour Name {
994*5113495bSYour Name 	spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ACTIVE. Returning val=%u",
995*5113495bSYour Name 		       function_name, output);
996*5113495bSYour Name }
997*5113495bSYour Name 
998*5113495bSYour Name /**
999*5113495bSYour Name  * target_if_log_read_spectral_enabled() - Helper function to log whether
1000*5113495bSYour Name  * spectral is enabled after reading cache
1001*5113495bSYour Name  * @function_name: Function name
1002*5113495bSYour Name  * @output: whether spectral is enabled or not
1003*5113495bSYour Name  *
1004*5113495bSYour Name  * Helper function to log whether spectral is enabled after reading cache
1005*5113495bSYour Name  *
1006*5113495bSYour Name  * Return: none
1007*5113495bSYour Name  */
1008*5113495bSYour Name static void
target_if_log_read_spectral_enabled(const char * function_name,unsigned char output)1009*5113495bSYour Name target_if_log_read_spectral_enabled(
1010*5113495bSYour Name 	const char *function_name,
1011*5113495bSYour Name 	unsigned char output)
1012*5113495bSYour Name {
1013*5113495bSYour Name 	spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ENABLED. Returning val=%u",
1014*5113495bSYour Name 		       function_name, output);
1015*5113495bSYour Name }
1016*5113495bSYour Name 
1017*5113495bSYour Name /**
1018*5113495bSYour Name  * target_if_log_read_spectral_params() - log spectral parameters
1019*5113495bSYour Name  * @function_name: Function name
1020*5113495bSYour Name  * @pparam: Spectral parameters
1021*5113495bSYour Name  *
1022*5113495bSYour Name  * Helper function to log spectral parameters after reading cache
1023*5113495bSYour Name  *
1024*5113495bSYour Name  * Return: none
1025*5113495bSYour Name  */
1026*5113495bSYour Name static void
target_if_log_read_spectral_params(const char * function_name,struct spectral_config * pparam)1027*5113495bSYour Name target_if_log_read_spectral_params(
1028*5113495bSYour Name 	const char *function_name,
1029*5113495bSYour Name 	struct spectral_config *pparam)
1030*5113495bSYour Name {
1031*5113495bSYour Name 	spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_PARAMS. Returning following params:\nss_count = %u\nss_period = %u\nss_recapture = %u\nss_spectral_pri = %u\nss_fft_size = %u\nss_gc_ena = %u\nss_restart_ena = %u\nss_noise_floor_ref = %d\nss_init_delay = %u\nss_nb_tone_thr = %u\nss_str_bin_thr = %u\nss_wb_rpt_mode = %u\nss_rssi_rpt_mode = %u\nss_rssi_thr = %d\nss_pwr_format = %u\nss_rpt_mode = %u\nss_bin_scale = %u\nss_dbm_adj = %u\nss_chn_mask = %u\nss_frequency1=%u\nss_frequency2=%u\n",
1032*5113495bSYour Name 		       function_name,
1033*5113495bSYour Name 		       pparam->ss_count,
1034*5113495bSYour Name 		       pparam->ss_period,
1035*5113495bSYour Name 		       pparam->ss_recapture,
1036*5113495bSYour Name 		       pparam->ss_spectral_pri,
1037*5113495bSYour Name 		       pparam->ss_fft_size,
1038*5113495bSYour Name 		       pparam->ss_gc_ena,
1039*5113495bSYour Name 		       pparam->ss_restart_ena,
1040*5113495bSYour Name 		       (int8_t)pparam->ss_noise_floor_ref,
1041*5113495bSYour Name 		       pparam->ss_init_delay,
1042*5113495bSYour Name 		       pparam->ss_nb_tone_thr,
1043*5113495bSYour Name 		       pparam->ss_str_bin_thr,
1044*5113495bSYour Name 		       pparam->ss_wb_rpt_mode,
1045*5113495bSYour Name 		       pparam->ss_rssi_rpt_mode,
1046*5113495bSYour Name 		       (int8_t)pparam->ss_rssi_thr,
1047*5113495bSYour Name 		       pparam->ss_pwr_format,
1048*5113495bSYour Name 		       pparam->ss_rpt_mode,
1049*5113495bSYour Name 		       pparam->ss_bin_scale,
1050*5113495bSYour Name 		       pparam->ss_dbm_adj,
1051*5113495bSYour Name 		       pparam->ss_chn_mask,
1052*5113495bSYour Name 		       pparam->ss_frequency.cfreq1,
1053*5113495bSYour Name 		       pparam->ss_frequency.cfreq2);
1054*5113495bSYour Name }
1055*5113495bSYour Name 
1056*5113495bSYour Name /**
1057*5113495bSYour Name  * target_if_log_read_spectral_active_catch_validate() - Helper function to
1058*5113495bSYour Name  * log whether spectral is active after initializing the cache
1059*5113495bSYour Name  * @function_name: Function name
1060*5113495bSYour Name  * @output: whether spectral is active or not
1061*5113495bSYour Name  *
1062*5113495bSYour Name  * Helper function to log whether spectral is active after initializing cache
1063*5113495bSYour Name  *
1064*5113495bSYour Name  * Return: none
1065*5113495bSYour Name  */
1066*5113495bSYour Name static void
target_if_log_read_spectral_active_catch_validate(const char * function_name,unsigned char output)1067*5113495bSYour Name target_if_log_read_spectral_active_catch_validate(
1068*5113495bSYour Name 	const char *function_name,
1069*5113495bSYour Name 	unsigned char output)
1070*5113495bSYour Name {
1071*5113495bSYour Name 	spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ACTIVE on initial cache validation\nReturning val=%u",
1072*5113495bSYour Name 		       function_name, output);
1073*5113495bSYour Name }
1074*5113495bSYour Name 
1075*5113495bSYour Name /**
1076*5113495bSYour Name  * target_if_log_read_spectral_enabled_catch_validate() - Helper function to
1077*5113495bSYour Name  * log whether spectral is enabled after initializing the cache
1078*5113495bSYour Name  * @function_name: Function name
1079*5113495bSYour Name  * @output: whether spectral is enabled or not
1080*5113495bSYour Name  *
1081*5113495bSYour Name  * Helper function to log whether spectral is enabled after initializing cache
1082*5113495bSYour Name  *
1083*5113495bSYour Name  * Return: none
1084*5113495bSYour Name  */
1085*5113495bSYour Name static void
target_if_log_read_spectral_enabled_catch_validate(const char * function_name,unsigned char output)1086*5113495bSYour Name target_if_log_read_spectral_enabled_catch_validate(
1087*5113495bSYour Name 	const char *function_name,
1088*5113495bSYour Name 	unsigned char output)
1089*5113495bSYour Name {
1090*5113495bSYour Name 	spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ENABLED on initial cache validation\nReturning val=%u\n",
1091*5113495bSYour Name 		       function_name, output);
1092*5113495bSYour Name }
1093*5113495bSYour Name 
1094*5113495bSYour Name /**
1095*5113495bSYour Name  * target_if_log_read_spectral_params_catch_validate() - Helper function to
1096*5113495bSYour Name  * log spectral parameters after initializing the cache
1097*5113495bSYour Name  * @function_name: Function name
1098*5113495bSYour Name  * @pparam: Spectral parameters
1099*5113495bSYour Name  *
1100*5113495bSYour Name  * Helper function to log spectral parameters after initializing the cache
1101*5113495bSYour Name  *
1102*5113495bSYour Name  * Return: none
1103*5113495bSYour Name  */
1104*5113495bSYour Name static void
target_if_log_read_spectral_params_catch_validate(const char * function_name,struct spectral_config * pparam)1105*5113495bSYour Name target_if_log_read_spectral_params_catch_validate(
1106*5113495bSYour Name 	const char *function_name,
1107*5113495bSYour Name 	struct spectral_config *pparam)
1108*5113495bSYour Name {
1109*5113495bSYour Name 	spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_PARAMS on initial cache validation\nReturning following params:\nss_count = %u\nss_period = %u\nss_recapture = %u\nss_spectral_pri = %u\nss_fft_size = %u\nss_gc_ena = %u\nss_restart_ena = %u\nss_noise_floor_ref = %d\nss_init_delay = %u\nss_nb_tone_thr = %u\nss_str_bin_thr = %u\nss_wb_rpt_mode = %u\nss_rssi_rpt_mode = %u\nss_rssi_thr = %d\nss_pwr_format = %u\nss_rpt_mode = %u\nss_bin_scale = %u\nss_dbm_adj = %u\nss_chn_mask = %u",
1110*5113495bSYour Name 		       function_name,
1111*5113495bSYour Name 		       pparam->ss_count,
1112*5113495bSYour Name 		       pparam->ss_period,
1113*5113495bSYour Name 		       pparam->ss_recapture,
1114*5113495bSYour Name 		       pparam->ss_spectral_pri,
1115*5113495bSYour Name 		       pparam->ss_fft_size,
1116*5113495bSYour Name 		       pparam->ss_gc_ena,
1117*5113495bSYour Name 		       pparam->ss_restart_ena,
1118*5113495bSYour Name 		       (int8_t)pparam->ss_noise_floor_ref,
1119*5113495bSYour Name 		       pparam->ss_init_delay,
1120*5113495bSYour Name 		       pparam->ss_nb_tone_thr,
1121*5113495bSYour Name 		       pparam->ss_str_bin_thr,
1122*5113495bSYour Name 		       pparam->ss_wb_rpt_mode,
1123*5113495bSYour Name 		       pparam->ss_rssi_rpt_mode,
1124*5113495bSYour Name 		       (int8_t)pparam->ss_rssi_thr,
1125*5113495bSYour Name 		       pparam->ss_pwr_format,
1126*5113495bSYour Name 		       pparam->ss_rpt_mode,
1127*5113495bSYour Name 		       pparam->ss_bin_scale,
1128*5113495bSYour Name 		       pparam->ss_dbm_adj, pparam->ss_chn_mask);
1129*5113495bSYour Name }
1130*5113495bSYour Name 
1131*5113495bSYour Name /**
1132*5113495bSYour Name  * target_if_spectral_info_read() - Read spectral information from the cache.
1133*5113495bSYour Name  * @spectral: Pointer to Spectral target_if internal private data
1134*5113495bSYour Name  * @smode: Spectral scan mode
1135*5113495bSYour Name  * @specifier: target_if_spectral_info enumeration specifying which
1136*5113495bSYour Name  * information is required
1137*5113495bSYour Name  * @output: Void output pointer into which the information will be read
1138*5113495bSYour Name  * @output_len: size of object pointed to by output pointer
1139*5113495bSYour Name  *
1140*5113495bSYour Name  * Read spectral parameters or the desired state information from the cache.
1141*5113495bSYour Name  *
1142*5113495bSYour Name  * Return: 0 on success, negative error code on failure
1143*5113495bSYour Name  */
1144*5113495bSYour Name static int
target_if_spectral_info_read(struct target_if_spectral * spectral,enum spectral_scan_mode smode,enum target_if_spectral_info specifier,void * output,int output_len)1145*5113495bSYour Name target_if_spectral_info_read(
1146*5113495bSYour Name 	struct target_if_spectral *spectral,
1147*5113495bSYour Name 	enum spectral_scan_mode smode,
1148*5113495bSYour Name 	enum target_if_spectral_info specifier,
1149*5113495bSYour Name 	void *output, int output_len)
1150*5113495bSYour Name {
1151*5113495bSYour Name 	/*
1152*5113495bSYour Name 	 * Note: This function is designed to be able to accommodate
1153*5113495bSYour Name 	 * WMI reads for defaults, non-cacheable information, etc
1154*5113495bSYour Name 	 * if required.
1155*5113495bSYour Name 	 */
1156*5113495bSYour Name 	struct target_if_spectral_param_state_info *info;
1157*5113495bSYour Name 	int is_cacheable = 0;
1158*5113495bSYour Name 	int init_def_retval = 0;
1159*5113495bSYour Name 
1160*5113495bSYour Name 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
1161*5113495bSYour Name 		spectral_err("Invalid Spectral mode %u", smode);
1162*5113495bSYour Name 		return -EINVAL;
1163*5113495bSYour Name 	}
1164*5113495bSYour Name 	info = &spectral->param_info[smode];
1165*5113495bSYour Name 
1166*5113495bSYour Name 	if (!output)
1167*5113495bSYour Name 		return -EINVAL;
1168*5113495bSYour Name 
1169*5113495bSYour Name 	switch (specifier) {
1170*5113495bSYour Name 	case TARGET_IF_SPECTRAL_INFO_ACTIVE:
1171*5113495bSYour Name 		if (output_len != sizeof(info->osps_cache.osc_spectral_active))
1172*5113495bSYour Name 			return -EINVAL;
1173*5113495bSYour Name 		is_cacheable = 1;
1174*5113495bSYour Name 		break;
1175*5113495bSYour Name 
1176*5113495bSYour Name 	case TARGET_IF_SPECTRAL_INFO_ENABLED:
1177*5113495bSYour Name 		if (output_len != sizeof(info->osps_cache.osc_spectral_enabled))
1178*5113495bSYour Name 			return -EINVAL;
1179*5113495bSYour Name 		is_cacheable = 1;
1180*5113495bSYour Name 		break;
1181*5113495bSYour Name 
1182*5113495bSYour Name 	case TARGET_IF_SPECTRAL_INFO_PARAMS:
1183*5113495bSYour Name 		if (output_len != sizeof(info->osps_cache.osc_params))
1184*5113495bSYour Name 			return -EINVAL;
1185*5113495bSYour Name 		is_cacheable = 1;
1186*5113495bSYour Name 		break;
1187*5113495bSYour Name 
1188*5113495bSYour Name 	default:
1189*5113495bSYour Name 		spectral_err("Unknown target_if_spectral_info specifier");
1190*5113495bSYour Name 		return -EINVAL;
1191*5113495bSYour Name 	}
1192*5113495bSYour Name 
1193*5113495bSYour Name 	qdf_spin_lock_bh(&info->osps_lock);
1194*5113495bSYour Name 
1195*5113495bSYour Name 	if (is_cacheable) {
1196*5113495bSYour Name 		if (info->osps_cache.osc_is_valid) {
1197*5113495bSYour Name 			switch (specifier) {
1198*5113495bSYour Name 			case TARGET_IF_SPECTRAL_INFO_ACTIVE:
1199*5113495bSYour Name 				qdf_mem_copy(
1200*5113495bSYour Name 				  output,
1201*5113495bSYour Name 				  &info->osps_cache.osc_spectral_active,
1202*5113495bSYour Name 				  sizeof(info->osps_cache.osc_spectral_active));
1203*5113495bSYour Name 
1204*5113495bSYour Name 				target_if_log_read_spectral_active(
1205*5113495bSYour Name 					__func__,
1206*5113495bSYour Name 					*((unsigned char *)output));
1207*5113495bSYour Name 				break;
1208*5113495bSYour Name 
1209*5113495bSYour Name 			case TARGET_IF_SPECTRAL_INFO_ENABLED:
1210*5113495bSYour Name 				qdf_mem_copy(
1211*5113495bSYour Name 				  output,
1212*5113495bSYour Name 				  &info->osps_cache.osc_spectral_enabled,
1213*5113495bSYour Name 				  sizeof(
1214*5113495bSYour Name 					info->osps_cache.osc_spectral_enabled));
1215*5113495bSYour Name 
1216*5113495bSYour Name 				target_if_log_read_spectral_enabled(
1217*5113495bSYour Name 					__func__,
1218*5113495bSYour Name 					*((unsigned char *)output));
1219*5113495bSYour Name 				break;
1220*5113495bSYour Name 
1221*5113495bSYour Name 			case TARGET_IF_SPECTRAL_INFO_PARAMS:
1222*5113495bSYour Name 				qdf_mem_copy(
1223*5113495bSYour Name 				  output,
1224*5113495bSYour Name 				  &info->osps_cache.osc_params,
1225*5113495bSYour Name 				  sizeof(info->osps_cache.osc_params));
1226*5113495bSYour Name 
1227*5113495bSYour Name 				target_if_log_read_spectral_params(
1228*5113495bSYour Name 					__func__,
1229*5113495bSYour Name 					(struct spectral_config *)output);
1230*5113495bSYour Name 				break;
1231*5113495bSYour Name 
1232*5113495bSYour Name 			default:
1233*5113495bSYour Name 				/* We can't reach this point */
1234*5113495bSYour Name 				break;
1235*5113495bSYour Name 			}
1236*5113495bSYour Name 			qdf_spin_unlock_bh(&info->osps_lock);
1237*5113495bSYour Name 			return 0;
1238*5113495bSYour Name 		}
1239*5113495bSYour Name 	}
1240*5113495bSYour Name 
1241*5113495bSYour Name 	/* Cache is invalid */
1242*5113495bSYour Name 
1243*5113495bSYour Name 	/*
1244*5113495bSYour Name 	 * If WMI Reads are implemented to fetch defaults/non-cacheable info,
1245*5113495bSYour Name 	 * then the below implementation will change
1246*5113495bSYour Name 	 */
1247*5113495bSYour Name 	init_def_retval =
1248*5113495bSYour Name 			target_if_spectral_info_init_defaults(spectral, smode);
1249*5113495bSYour Name 	if (init_def_retval != QDF_STATUS_SUCCESS) {
1250*5113495bSYour Name 		qdf_spin_unlock_bh(&info->osps_lock);
1251*5113495bSYour Name 		if (init_def_retval == QDF_STATUS_E_NOENT)
1252*5113495bSYour Name 			return -ENOENT;
1253*5113495bSYour Name 		else
1254*5113495bSYour Name 			return -EINVAL;
1255*5113495bSYour Name 	}
1256*5113495bSYour Name 	/* target_if_spectral_info_init_defaults() has set cache to valid */
1257*5113495bSYour Name 
1258*5113495bSYour Name 	switch (specifier) {
1259*5113495bSYour Name 	case TARGET_IF_SPECTRAL_INFO_ACTIVE:
1260*5113495bSYour Name 		qdf_mem_copy(output,
1261*5113495bSYour Name 			     &info->osps_cache.osc_spectral_active,
1262*5113495bSYour Name 			     sizeof(info->osps_cache.osc_spectral_active));
1263*5113495bSYour Name 
1264*5113495bSYour Name 		target_if_log_read_spectral_active_catch_validate(
1265*5113495bSYour Name 			__func__,
1266*5113495bSYour Name 			*((unsigned char *)output));
1267*5113495bSYour Name 		break;
1268*5113495bSYour Name 
1269*5113495bSYour Name 	case TARGET_IF_SPECTRAL_INFO_ENABLED:
1270*5113495bSYour Name 		qdf_mem_copy(output,
1271*5113495bSYour Name 			     &info->osps_cache.osc_spectral_enabled,
1272*5113495bSYour Name 			     sizeof(info->osps_cache.osc_spectral_enabled));
1273*5113495bSYour Name 
1274*5113495bSYour Name 		target_if_log_read_spectral_enabled_catch_validate(
1275*5113495bSYour Name 			__func__,
1276*5113495bSYour Name 			*((unsigned char *)output));
1277*5113495bSYour Name 		break;
1278*5113495bSYour Name 
1279*5113495bSYour Name 	case TARGET_IF_SPECTRAL_INFO_PARAMS:
1280*5113495bSYour Name 		qdf_mem_copy(output,
1281*5113495bSYour Name 			     &info->osps_cache.osc_params,
1282*5113495bSYour Name 			     sizeof(info->osps_cache.osc_params));
1283*5113495bSYour Name 
1284*5113495bSYour Name 		target_if_log_read_spectral_params_catch_validate(
1285*5113495bSYour Name 			__func__,
1286*5113495bSYour Name 			(struct spectral_config *)output);
1287*5113495bSYour Name 
1288*5113495bSYour Name 		break;
1289*5113495bSYour Name 
1290*5113495bSYour Name 	default:
1291*5113495bSYour Name 		/* We can't reach this point */
1292*5113495bSYour Name 		break;
1293*5113495bSYour Name 	}
1294*5113495bSYour Name 
1295*5113495bSYour Name 	qdf_spin_unlock_bh(&info->osps_lock);
1296*5113495bSYour Name 
1297*5113495bSYour Name 	return 0;
1298*5113495bSYour Name }
1299*5113495bSYour Name 
1300*5113495bSYour Name /**
1301*5113495bSYour Name  * target_if_log_write_spectral_active() - Helper function to log inputs and
1302*5113495bSYour Name  * return value of call to configure the Spectral 'active' configuration,
1303*5113495bSYour Name  * TARGET_IF_SPECTRAL_INFO_ACTIVE into firmware
1304*5113495bSYour Name  * @function_name: Function name in which this is called
1305*5113495bSYour Name  * @pval: whether spectral is active or not
1306*5113495bSYour Name  * @ret: return value of the firmware write function
1307*5113495bSYour Name  *
1308*5113495bSYour Name  * Return: none
1309*5113495bSYour Name  */
1310*5113495bSYour Name static void
target_if_log_write_spectral_active(const char * function_name,uint8_t pval,int ret)1311*5113495bSYour Name target_if_log_write_spectral_active(
1312*5113495bSYour Name 	const char *function_name,
1313*5113495bSYour Name 	uint8_t pval,
1314*5113495bSYour Name 	int ret)
1315*5113495bSYour Name {
1316*5113495bSYour Name 	spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ACTIVE with val=%u status=%d",
1317*5113495bSYour Name 		       function_name, pval, ret);
1318*5113495bSYour Name }
1319*5113495bSYour Name 
1320*5113495bSYour Name /**
1321*5113495bSYour Name  * target_if_log_write_spectral_enabled() - Helper function to log inputs and
1322*5113495bSYour Name  * return value of call to configure the Spectral 'enabled' configuration,
1323*5113495bSYour Name  * TARGET_IF_SPECTRAL_INFO_ENABLED into firmware
1324*5113495bSYour Name  * @function_name: Function name in which this is called
1325*5113495bSYour Name  * @pval: whether spectral is enabled or not
1326*5113495bSYour Name  * @ret: return value of the firmware write function
1327*5113495bSYour Name  *
1328*5113495bSYour Name  * Return: none
1329*5113495bSYour Name  */
1330*5113495bSYour Name static void
target_if_log_write_spectral_enabled(const char * function_name,uint8_t pval,int ret)1331*5113495bSYour Name target_if_log_write_spectral_enabled(
1332*5113495bSYour Name 	const char *function_name,
1333*5113495bSYour Name 	uint8_t pval,
1334*5113495bSYour Name 	int ret)
1335*5113495bSYour Name {
1336*5113495bSYour Name 	spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ENABLED with val=%u status=%d",
1337*5113495bSYour Name 		       function_name, pval, ret);
1338*5113495bSYour Name }
1339*5113495bSYour Name 
1340*5113495bSYour Name /**
1341*5113495bSYour Name  * target_if_log_write_spectral_params() - Helper function to log inputs and
1342*5113495bSYour Name  * return value of call to configure Spectral parameters,
1343*5113495bSYour Name  * TARGET_IF_SPECTRAL_INFO_PARAMS into firmware
1344*5113495bSYour Name  * @param: Spectral parameters
1345*5113495bSYour Name  * @function_name: Function name in which this is called
1346*5113495bSYour Name  * @ret: return value of the firmware write function
1347*5113495bSYour Name  *
1348*5113495bSYour Name  * Return: none
1349*5113495bSYour Name  */
1350*5113495bSYour Name static void
target_if_log_write_spectral_params(struct spectral_config * param,const char * function_name,int ret)1351*5113495bSYour Name target_if_log_write_spectral_params(
1352*5113495bSYour Name 	struct spectral_config *param,
1353*5113495bSYour Name 	const char *function_name,
1354*5113495bSYour Name 	int ret)
1355*5113495bSYour Name {
1356*5113495bSYour Name 	spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_PARAMS. Params:\nss_count = %u\nss_period = %u\nss_recapture = %u\nss_spectral_pri = %u\nss_fft_size = %u\nss_gc_ena = %u\nss_restart_ena = %u\nss_noise_floor_ref = %d\nss_init_delay = %u\nss_nb_tone_thr = %u\nss_str_bin_thr = %u\nss_wb_rpt_mode = %u\nss_rssi_rpt_mode = %u\nss_rssi_thr = %d\nss_pwr_format = %u\nss_rpt_mode = %u\nss_bin_scale = %u\nss_dbm_adj = %u\nss_chn_mask = %u\nss_frequency1=%u\nss_frequency2=%u\nstatus = %d",
1357*5113495bSYour Name 		       function_name,
1358*5113495bSYour Name 		       param->ss_count,
1359*5113495bSYour Name 		       param->ss_period,
1360*5113495bSYour Name 		       param->ss_recapture,
1361*5113495bSYour Name 		       param->ss_spectral_pri,
1362*5113495bSYour Name 		       param->ss_fft_size,
1363*5113495bSYour Name 		       param->ss_gc_ena,
1364*5113495bSYour Name 		       param->ss_restart_ena,
1365*5113495bSYour Name 		       (int8_t)param->ss_noise_floor_ref,
1366*5113495bSYour Name 		       param->ss_init_delay,
1367*5113495bSYour Name 		       param->ss_nb_tone_thr,
1368*5113495bSYour Name 		       param->ss_str_bin_thr,
1369*5113495bSYour Name 		       param->ss_wb_rpt_mode,
1370*5113495bSYour Name 		       param->ss_rssi_rpt_mode,
1371*5113495bSYour Name 		       (int8_t)param->ss_rssi_thr,
1372*5113495bSYour Name 		       param->ss_pwr_format,
1373*5113495bSYour Name 		       param->ss_rpt_mode,
1374*5113495bSYour Name 		       param->ss_bin_scale,
1375*5113495bSYour Name 		       param->ss_dbm_adj,
1376*5113495bSYour Name 		       param->ss_chn_mask,
1377*5113495bSYour Name 		       param->ss_frequency.cfreq1,
1378*5113495bSYour Name 		       param->ss_frequency.cfreq2,
1379*5113495bSYour Name 		       ret);
1380*5113495bSYour Name }
1381*5113495bSYour Name 
1382*5113495bSYour Name /**
1383*5113495bSYour Name  * target_if_spectral_info_write() - Write Spectral information to the
1384*5113495bSYour Name  * firmware, and update cache
1385*5113495bSYour Name  * @spectral: Pointer to Spectral target_if internal private data
1386*5113495bSYour Name  * @smode: Spectral scan mode
1387*5113495bSYour Name  * @specifier: target_if_spectral_info enumeration specifying which
1388*5113495bSYour Name  * information is involved
1389*5113495bSYour Name  * @input: void input pointer containing the information to be written
1390*5113495bSYour Name  * @input_len: size of object pointed to by input pointer
1391*5113495bSYour Name  *
1392*5113495bSYour Name  * Write Spectral parameters or the desired state information to
1393*5113495bSYour Name  * the firmware, and update cache
1394*5113495bSYour Name  *
1395*5113495bSYour Name  * Return: 0 on success, negative error code on failure
1396*5113495bSYour Name  */
1397*5113495bSYour Name static int
target_if_spectral_info_write(struct target_if_spectral * spectral,enum spectral_scan_mode smode,enum target_if_spectral_info specifier,void * input,int input_len)1398*5113495bSYour Name target_if_spectral_info_write(
1399*5113495bSYour Name 	struct target_if_spectral *spectral,
1400*5113495bSYour Name 	enum spectral_scan_mode smode,
1401*5113495bSYour Name 	enum target_if_spectral_info specifier,
1402*5113495bSYour Name 	void *input, int input_len)
1403*5113495bSYour Name {
1404*5113495bSYour Name 	struct target_if_spectral_param_state_info *info;
1405*5113495bSYour Name 	int ret;
1406*5113495bSYour Name 	uint8_t *pval = NULL;
1407*5113495bSYour Name 	struct spectral_config *param = NULL;
1408*5113495bSYour Name 
1409*5113495bSYour Name 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
1410*5113495bSYour Name 		spectral_err("Invalid Spectral mode %u", smode);
1411*5113495bSYour Name 		return -EINVAL;
1412*5113495bSYour Name 	}
1413*5113495bSYour Name 	info = &spectral->param_info[smode];
1414*5113495bSYour Name 
1415*5113495bSYour Name 	if (!input)
1416*5113495bSYour Name 		return -EINVAL;
1417*5113495bSYour Name 
1418*5113495bSYour Name 	switch (specifier) {
1419*5113495bSYour Name 	case TARGET_IF_SPECTRAL_INFO_ACTIVE:
1420*5113495bSYour Name 		if (input_len != sizeof(info->osps_cache.osc_spectral_active))
1421*5113495bSYour Name 			return -EINVAL;
1422*5113495bSYour Name 
1423*5113495bSYour Name 		pval = (uint8_t *)input;
1424*5113495bSYour Name 
1425*5113495bSYour Name 		qdf_spin_lock_bh(&info->osps_lock);
1426*5113495bSYour Name 		ret = target_if_send_vdev_spectral_enable_cmd(spectral, smode,
1427*5113495bSYour Name 							      1, *pval, 0, 0);
1428*5113495bSYour Name 
1429*5113495bSYour Name 		target_if_log_write_spectral_active(
1430*5113495bSYour Name 			__func__,
1431*5113495bSYour Name 			*pval,
1432*5113495bSYour Name 			ret);
1433*5113495bSYour Name 
1434*5113495bSYour Name 		if (ret < 0) {
1435*5113495bSYour Name 			spectral_err("target_if_send_vdev_spectral_enable_cmd failed with error=%d",
1436*5113495bSYour Name 				     ret);
1437*5113495bSYour Name 			qdf_spin_unlock_bh(&info->osps_lock);
1438*5113495bSYour Name 			return ret;
1439*5113495bSYour Name 		}
1440*5113495bSYour Name 
1441*5113495bSYour Name 		info->osps_cache.osc_spectral_active = *pval;
1442*5113495bSYour Name 
1443*5113495bSYour Name 		/* The cache is now valid */
1444*5113495bSYour Name 		info->osps_cache.osc_is_valid = 1;
1445*5113495bSYour Name 
1446*5113495bSYour Name 		qdf_spin_unlock_bh(&info->osps_lock);
1447*5113495bSYour Name 		break;
1448*5113495bSYour Name 
1449*5113495bSYour Name 	case TARGET_IF_SPECTRAL_INFO_ENABLED:
1450*5113495bSYour Name 		if (input_len != sizeof(info->osps_cache.osc_spectral_enabled))
1451*5113495bSYour Name 			return -EINVAL;
1452*5113495bSYour Name 
1453*5113495bSYour Name 		pval = (uint8_t *)input;
1454*5113495bSYour Name 
1455*5113495bSYour Name 		qdf_spin_lock_bh(&info->osps_lock);
1456*5113495bSYour Name 		ret = target_if_send_vdev_spectral_enable_cmd(spectral, smode,
1457*5113495bSYour Name 							      0, 0, 1, *pval);
1458*5113495bSYour Name 
1459*5113495bSYour Name 		target_if_log_write_spectral_enabled(
1460*5113495bSYour Name 			__func__,
1461*5113495bSYour Name 			*pval,
1462*5113495bSYour Name 			ret);
1463*5113495bSYour Name 
1464*5113495bSYour Name 		if (ret < 0) {
1465*5113495bSYour Name 			spectral_err("target_if_send_vdev_spectral_enable_cmd failed with error=%d",
1466*5113495bSYour Name 				     ret);
1467*5113495bSYour Name 			qdf_spin_unlock_bh(&info->osps_lock);
1468*5113495bSYour Name 			return ret;
1469*5113495bSYour Name 		}
1470*5113495bSYour Name 
1471*5113495bSYour Name 		info->osps_cache.osc_spectral_enabled = *pval;
1472*5113495bSYour Name 
1473*5113495bSYour Name 		/* The cache is now valid */
1474*5113495bSYour Name 		info->osps_cache.osc_is_valid = 1;
1475*5113495bSYour Name 
1476*5113495bSYour Name 		qdf_spin_unlock_bh(&info->osps_lock);
1477*5113495bSYour Name 		break;
1478*5113495bSYour Name 
1479*5113495bSYour Name 	case TARGET_IF_SPECTRAL_INFO_PARAMS:
1480*5113495bSYour Name 		if (input_len != sizeof(info->osps_cache.osc_params))
1481*5113495bSYour Name 			return -EINVAL;
1482*5113495bSYour Name 
1483*5113495bSYour Name 		param = (struct spectral_config *)input;
1484*5113495bSYour Name 
1485*5113495bSYour Name 		qdf_spin_lock_bh(&info->osps_lock);
1486*5113495bSYour Name 		ret = target_if_send_vdev_spectral_configure_cmd(spectral,
1487*5113495bSYour Name 								 smode, param);
1488*5113495bSYour Name 
1489*5113495bSYour Name 		target_if_log_write_spectral_params(
1490*5113495bSYour Name 			param,
1491*5113495bSYour Name 			__func__,
1492*5113495bSYour Name 			ret);
1493*5113495bSYour Name 
1494*5113495bSYour Name 		if (ret < 0) {
1495*5113495bSYour Name 			spectral_err("target_if_send_vdev_spectral_configure_cmd failed with error=%d",
1496*5113495bSYour Name 				     ret);
1497*5113495bSYour Name 			qdf_spin_unlock_bh(&info->osps_lock);
1498*5113495bSYour Name 			return ret;
1499*5113495bSYour Name 		}
1500*5113495bSYour Name 
1501*5113495bSYour Name 		qdf_mem_copy(&info->osps_cache.osc_params,
1502*5113495bSYour Name 			     param, sizeof(info->osps_cache.osc_params));
1503*5113495bSYour Name 
1504*5113495bSYour Name 		/* The cache is now valid */
1505*5113495bSYour Name 		info->osps_cache.osc_is_valid = 1;
1506*5113495bSYour Name 
1507*5113495bSYour Name 		qdf_spin_unlock_bh(&info->osps_lock);
1508*5113495bSYour Name 		break;
1509*5113495bSYour Name 
1510*5113495bSYour Name 	default:
1511*5113495bSYour Name 		spectral_err("Unknown target_if_spectral_info specifier");
1512*5113495bSYour Name 		return -EINVAL;
1513*5113495bSYour Name 	}
1514*5113495bSYour Name 
1515*5113495bSYour Name 	return 0;
1516*5113495bSYour Name }
1517*5113495bSYour Name 
1518*5113495bSYour Name /**
1519*5113495bSYour Name  * target_if_spectral_get_tsf64() - Function to get the TSF value
1520*5113495bSYour Name  * @arg: Pointer to handle for Spectral target_if internal private data
1521*5113495bSYour Name  *
1522*5113495bSYour Name  * Get the last TSF received in WMI buffer
1523*5113495bSYour Name  *
1524*5113495bSYour Name  * Return: TSF value
1525*5113495bSYour Name  */
1526*5113495bSYour Name static uint64_t
target_if_spectral_get_tsf64(void * arg)1527*5113495bSYour Name target_if_spectral_get_tsf64(void *arg)
1528*5113495bSYour Name {
1529*5113495bSYour Name 	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
1530*5113495bSYour Name 
1531*5113495bSYour Name 	return spectral->tsf64;
1532*5113495bSYour Name }
1533*5113495bSYour Name 
1534*5113495bSYour Name /**
1535*5113495bSYour Name  * target_if_spectral_get_capability() - Function to get whether a
1536*5113495bSYour Name  * given Spectral hardware capability is available
1537*5113495bSYour Name  * @arg: Pointer to handle for Spectral target_if internal private data
1538*5113495bSYour Name  * @type: Spectral hardware capability type
1539*5113495bSYour Name  *
1540*5113495bSYour Name  * Get whether a given Spectral hardware capability is available
1541*5113495bSYour Name  *
1542*5113495bSYour Name  * Return: True if the capability is available, false if the capability is not
1543*5113495bSYour Name  * available
1544*5113495bSYour Name  */
1545*5113495bSYour Name uint32_t
target_if_spectral_get_capability(void * arg,enum spectral_capability_type type)1546*5113495bSYour Name target_if_spectral_get_capability(void *arg, enum spectral_capability_type type)
1547*5113495bSYour Name {
1548*5113495bSYour Name 	int status = STATUS_FAIL;
1549*5113495bSYour Name 
1550*5113495bSYour Name 	switch (type) {
1551*5113495bSYour Name 	case SPECTRAL_CAP_PHYDIAG:
1552*5113495bSYour Name 	case SPECTRAL_CAP_RADAR:
1553*5113495bSYour Name 	case SPECTRAL_CAP_SPECTRAL_SCAN:
1554*5113495bSYour Name 	case SPECTRAL_CAP_ADVNCD_SPECTRAL_SCAN:
1555*5113495bSYour Name 		status = STATUS_PASS;
1556*5113495bSYour Name 		break;
1557*5113495bSYour Name 	default:
1558*5113495bSYour Name 		status = STATUS_FAIL;
1559*5113495bSYour Name 	}
1560*5113495bSYour Name 	return status;
1561*5113495bSYour Name }
1562*5113495bSYour Name 
1563*5113495bSYour Name /**
1564*5113495bSYour Name  * target_if_spectral_set_rxfilter() - Set the RX Filter before Spectral start
1565*5113495bSYour Name  * @arg: Pointer to handle for Spectral target_if internal private data
1566*5113495bSYour Name  * @rxfilter: Rx filter to be used
1567*5113495bSYour Name  *
1568*5113495bSYour Name  * Note: This is only a placeholder function. It is not currently required since
1569*5113495bSYour Name  * FW should be taking care of setting the required filters.
1570*5113495bSYour Name  *
1571*5113495bSYour Name  * Return: 0
1572*5113495bSYour Name  */
1573*5113495bSYour Name uint32_t
target_if_spectral_set_rxfilter(void * arg,int rxfilter)1574*5113495bSYour Name target_if_spectral_set_rxfilter(void *arg, int rxfilter)
1575*5113495bSYour Name {
1576*5113495bSYour Name 	/*
1577*5113495bSYour Name 	 * Will not be required since enabling of spectral in firmware
1578*5113495bSYour Name 	 * will take care of this
1579*5113495bSYour Name 	 */
1580*5113495bSYour Name 	return 0;
1581*5113495bSYour Name }
1582*5113495bSYour Name 
1583*5113495bSYour Name /**
1584*5113495bSYour Name  * target_if_spectral_get_rxfilter() - Get the current RX Filter settings
1585*5113495bSYour Name  * @arg: Pointer to handle for Spectral target_if internal private data
1586*5113495bSYour Name  *
1587*5113495bSYour Name  * Note: This is only a placeholder function. It is not currently required since
1588*5113495bSYour Name  * FW should be taking care of setting the required filters.
1589*5113495bSYour Name  *
1590*5113495bSYour Name  * Return: 0
1591*5113495bSYour Name  */
1592*5113495bSYour Name uint32_t
target_if_spectral_get_rxfilter(void * arg)1593*5113495bSYour Name target_if_spectral_get_rxfilter(void *arg)
1594*5113495bSYour Name {
1595*5113495bSYour Name 	/*
1596*5113495bSYour Name 	 * Will not be required since enabling of spectral in firmware
1597*5113495bSYour Name 	 * will take care of this
1598*5113495bSYour Name 	 */
1599*5113495bSYour Name 	return 0;
1600*5113495bSYour Name }
1601*5113495bSYour Name 
1602*5113495bSYour Name /**
1603*5113495bSYour Name  * target_if_sops_is_spectral_active() - Get whether Spectral is active
1604*5113495bSYour Name  * @arg: Pointer to handle for Spectral target_if internal private data
1605*5113495bSYour Name  * @smode: Spectral scan mode
1606*5113495bSYour Name  *
1607*5113495bSYour Name  * Function to check whether Spectral is active
1608*5113495bSYour Name  *
1609*5113495bSYour Name  * Return: True if Spectral is active, false if Spectral is not active
1610*5113495bSYour Name  */
1611*5113495bSYour Name uint32_t
target_if_sops_is_spectral_active(void * arg,enum spectral_scan_mode smode)1612*5113495bSYour Name target_if_sops_is_spectral_active(void *arg, enum spectral_scan_mode smode)
1613*5113495bSYour Name {
1614*5113495bSYour Name 	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
1615*5113495bSYour Name 	uint8_t val = 0;
1616*5113495bSYour Name 	int ret;
1617*5113495bSYour Name 
1618*5113495bSYour Name 	ret = target_if_spectral_info_read(
1619*5113495bSYour Name 		spectral,
1620*5113495bSYour Name 		smode,
1621*5113495bSYour Name 		TARGET_IF_SPECTRAL_INFO_ACTIVE,
1622*5113495bSYour Name 		&val, sizeof(val));
1623*5113495bSYour Name 
1624*5113495bSYour Name 	if (ret != 0) {
1625*5113495bSYour Name 		/*
1626*5113495bSYour Name 		 * Could not determine if Spectral is active.
1627*5113495bSYour Name 		 * Return false as a safe value.
1628*5113495bSYour Name 		 * XXX: Consider changing the function prototype
1629*5113495bSYour Name 		 * to be able to indicate failure to fetch value.
1630*5113495bSYour Name 		 */
1631*5113495bSYour Name 		return 0;
1632*5113495bSYour Name 	}
1633*5113495bSYour Name 
1634*5113495bSYour Name 	return val;
1635*5113495bSYour Name }
1636*5113495bSYour Name 
1637*5113495bSYour Name /**
1638*5113495bSYour Name  * target_if_sops_is_spectral_enabled() - Get whether Spectral is enabled
1639*5113495bSYour Name  * @arg: Pointer to handle for Spectral target_if internal private data
1640*5113495bSYour Name  * @smode: Spectral scan mode
1641*5113495bSYour Name  *
1642*5113495bSYour Name  * Function to check whether Spectral is enabled
1643*5113495bSYour Name  *
1644*5113495bSYour Name  * Return: True if Spectral is enabled, false if Spectral is not enabled
1645*5113495bSYour Name  */
1646*5113495bSYour Name uint32_t
target_if_sops_is_spectral_enabled(void * arg,enum spectral_scan_mode smode)1647*5113495bSYour Name target_if_sops_is_spectral_enabled(void *arg, enum spectral_scan_mode smode)
1648*5113495bSYour Name {
1649*5113495bSYour Name 	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
1650*5113495bSYour Name 	uint8_t val = 0;
1651*5113495bSYour Name 	int ret;
1652*5113495bSYour Name 
1653*5113495bSYour Name 	ret = target_if_spectral_info_read(
1654*5113495bSYour Name 		spectral,
1655*5113495bSYour Name 		smode,
1656*5113495bSYour Name 		TARGET_IF_SPECTRAL_INFO_ENABLED,
1657*5113495bSYour Name 		&val, sizeof(val));
1658*5113495bSYour Name 
1659*5113495bSYour Name 	if (ret != 0) {
1660*5113495bSYour Name 		/*
1661*5113495bSYour Name 		 * Could not determine if Spectral is enabled.
1662*5113495bSYour Name 		 * Return false as a safe value.
1663*5113495bSYour Name 		 * XXX: Consider changing the function prototype
1664*5113495bSYour Name 		 * to be able to indicate failure to fetch value.
1665*5113495bSYour Name 		 */
1666*5113495bSYour Name 		return 0;
1667*5113495bSYour Name 	}
1668*5113495bSYour Name 
1669*5113495bSYour Name 	return val;
1670*5113495bSYour Name }
1671*5113495bSYour Name 
1672*5113495bSYour Name /**
1673*5113495bSYour Name  * target_if_sops_start_spectral_scan() - Start Spectral scan
1674*5113495bSYour Name  * @arg: Pointer to handle for Spectral target_if internal private data
1675*5113495bSYour Name  * @smode: Spectral scan mode
1676*5113495bSYour Name  * @err: Spectral error code
1677*5113495bSYour Name  *
1678*5113495bSYour Name  * Function to start spectral scan
1679*5113495bSYour Name  *
1680*5113495bSYour Name  * Return: 0 on success else failure
1681*5113495bSYour Name  */
1682*5113495bSYour Name uint32_t
target_if_sops_start_spectral_scan(void * arg,enum spectral_scan_mode smode,enum spectral_cp_error_code * err)1683*5113495bSYour Name target_if_sops_start_spectral_scan(void *arg, enum spectral_scan_mode smode,
1684*5113495bSYour Name 				   enum spectral_cp_error_code *err)
1685*5113495bSYour Name {
1686*5113495bSYour Name 	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
1687*5113495bSYour Name 	uint8_t val = 1;
1688*5113495bSYour Name 	uint8_t enabled = 0;
1689*5113495bSYour Name 	int ret;
1690*5113495bSYour Name 
1691*5113495bSYour Name 	ret = target_if_spectral_info_read(
1692*5113495bSYour Name 		spectral,
1693*5113495bSYour Name 		smode,
1694*5113495bSYour Name 		TARGET_IF_SPECTRAL_INFO_ENABLED,
1695*5113495bSYour Name 		&enabled, sizeof(enabled));
1696*5113495bSYour Name 
1697*5113495bSYour Name 	if (ret != 0) {
1698*5113495bSYour Name 		/*
1699*5113495bSYour Name 		 * Could not determine if Spectral is enabled. Assume we need
1700*5113495bSYour Name 		 * to enable it
1701*5113495bSYour Name 		 */
1702*5113495bSYour Name 		enabled = 0;
1703*5113495bSYour Name 	}
1704*5113495bSYour Name 
1705*5113495bSYour Name 	if (!enabled) {
1706*5113495bSYour Name 		ret = target_if_spectral_info_write(
1707*5113495bSYour Name 			spectral,
1708*5113495bSYour Name 			smode,
1709*5113495bSYour Name 			TARGET_IF_SPECTRAL_INFO_ENABLED,
1710*5113495bSYour Name 			&val, sizeof(val));
1711*5113495bSYour Name 
1712*5113495bSYour Name 		if (ret != 0)
1713*5113495bSYour Name 			return ret;
1714*5113495bSYour Name 	}
1715*5113495bSYour Name 
1716*5113495bSYour Name 	ret = target_if_spectral_info_write(
1717*5113495bSYour Name 		spectral,
1718*5113495bSYour Name 		smode,
1719*5113495bSYour Name 		TARGET_IF_SPECTRAL_INFO_ACTIVE,
1720*5113495bSYour Name 		&val, sizeof(val));
1721*5113495bSYour Name 
1722*5113495bSYour Name 	if (ret != 0)
1723*5113495bSYour Name 		return ret;
1724*5113495bSYour Name 
1725*5113495bSYour Name 	return 0;
1726*5113495bSYour Name }
1727*5113495bSYour Name 
1728*5113495bSYour Name /**
1729*5113495bSYour Name  * target_if_sops_stop_spectral_scan() - Stop Spectral scan
1730*5113495bSYour Name  * @arg: Pointer to handle for Spectral target_if internal private data
1731*5113495bSYour Name  * @smode: Spectral scan mode
1732*5113495bSYour Name  *
1733*5113495bSYour Name  * Function to stop spectral scan
1734*5113495bSYour Name  *
1735*5113495bSYour Name  * Return: 0 on success else failure
1736*5113495bSYour Name  */
1737*5113495bSYour Name uint32_t
target_if_sops_stop_spectral_scan(void * arg,enum spectral_scan_mode smode)1738*5113495bSYour Name target_if_sops_stop_spectral_scan(void *arg, enum spectral_scan_mode smode)
1739*5113495bSYour Name {
1740*5113495bSYour Name 	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
1741*5113495bSYour Name 	uint8_t val = 0;
1742*5113495bSYour Name 	int tempret, ret = 0;
1743*5113495bSYour Name 	uint8_t enabled = 0;
1744*5113495bSYour Name 
1745*5113495bSYour Name 	tempret = target_if_spectral_info_read(
1746*5113495bSYour Name 		spectral,
1747*5113495bSYour Name 		smode,
1748*5113495bSYour Name 		TARGET_IF_SPECTRAL_INFO_ENABLED,
1749*5113495bSYour Name 		&enabled, sizeof(enabled));
1750*5113495bSYour Name 
1751*5113495bSYour Name 	if (tempret)
1752*5113495bSYour Name 		/*
1753*5113495bSYour Name 		 * Could not determine if Spectral is enabled. Assume scan is
1754*5113495bSYour Name 		 * not in progress
1755*5113495bSYour Name 		 */
1756*5113495bSYour Name 		enabled = 0;
1757*5113495bSYour Name 
1758*5113495bSYour Name 	/* if scan is not enabled, no need to send stop to FW */
1759*5113495bSYour Name 	if (!enabled)
1760*5113495bSYour Name 		return -EPERM;
1761*5113495bSYour Name 
1762*5113495bSYour Name 	tempret = target_if_spectral_info_write(
1763*5113495bSYour Name 			spectral,
1764*5113495bSYour Name 			smode,
1765*5113495bSYour Name 			TARGET_IF_SPECTRAL_INFO_ACTIVE,
1766*5113495bSYour Name 			&val, sizeof(val));
1767*5113495bSYour Name 
1768*5113495bSYour Name 	if (tempret != 0)
1769*5113495bSYour Name 		ret = tempret;
1770*5113495bSYour Name 
1771*5113495bSYour Name 	tempret = target_if_spectral_info_write(
1772*5113495bSYour Name 			spectral,
1773*5113495bSYour Name 			smode,
1774*5113495bSYour Name 			TARGET_IF_SPECTRAL_INFO_ENABLED,
1775*5113495bSYour Name 			&val, sizeof(val));
1776*5113495bSYour Name 
1777*5113495bSYour Name 	if (tempret != 0)
1778*5113495bSYour Name 		ret = tempret;
1779*5113495bSYour Name 
1780*5113495bSYour Name 	if (ret == 0 && smode == SPECTRAL_SCAN_MODE_AGILE) {
1781*5113495bSYour Name 		struct target_if_spectral_ops *p_sops;
1782*5113495bSYour Name 		struct spectral_config *sparams;
1783*5113495bSYour Name 
1784*5113495bSYour Name 		p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
1785*5113495bSYour Name 		sparams = &spectral->params[smode];
1786*5113495bSYour Name 		sparams->ss_frequency.cfreq1 = 0;
1787*5113495bSYour Name 		sparams->ss_frequency.cfreq2 = 0;
1788*5113495bSYour Name 
1789*5113495bSYour Name 		p_sops->configure_spectral(spectral, sparams, smode);
1790*5113495bSYour Name 	}
1791*5113495bSYour Name 
1792*5113495bSYour Name 	return ret;
1793*5113495bSYour Name }
1794*5113495bSYour Name 
1795*5113495bSYour Name /**
1796*5113495bSYour Name  * target_if_spectral_get_extension_channel() - Get the Extension channel
1797*5113495bSYour Name  * @arg: Pointer to handle for Spectral target_if internal private data
1798*5113495bSYour Name  * @smode: Spectral scan mode
1799*5113495bSYour Name  *
1800*5113495bSYour Name  * Function to get the current Extension channel (in MHz)
1801*5113495bSYour Name  *
1802*5113495bSYour Name  * Return: Current Extension channel (in MHz) on success, 0 on failure or if
1803*5113495bSYour Name  * extension channel is not present.
1804*5113495bSYour Name  */
1805*5113495bSYour Name uint32_t
target_if_spectral_get_extension_channel(void * arg,enum spectral_scan_mode smode)1806*5113495bSYour Name target_if_spectral_get_extension_channel(void *arg,
1807*5113495bSYour Name 					 enum spectral_scan_mode smode)
1808*5113495bSYour Name {
1809*5113495bSYour Name 	/*
1810*5113495bSYour Name 	 * XXX: Once we expand to use cases where Spectral could be activated
1811*5113495bSYour Name 	 * without a channel being set to VDEV, we need to consider returning a
1812*5113495bSYour Name 	 * negative value in case of failure and having all callers handle this.
1813*5113495bSYour Name 	 */
1814*5113495bSYour Name 
1815*5113495bSYour Name 	struct target_if_spectral *spectral = NULL;
1816*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev = NULL;
1817*5113495bSYour Name 	uint16_t sec20chan_freq = 0;
1818*5113495bSYour Name 
1819*5113495bSYour Name 	if (!arg) {
1820*5113495bSYour Name 		spectral_err("Null argument.");
1821*5113495bSYour Name 		return 0;
1822*5113495bSYour Name 	}
1823*5113495bSYour Name 
1824*5113495bSYour Name 	spectral = (struct target_if_spectral *)arg;
1825*5113495bSYour Name 
1826*5113495bSYour Name 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
1827*5113495bSYour Name 		spectral_err("Invalid Spectral mode %u", smode);
1828*5113495bSYour Name 		return 0;
1829*5113495bSYour Name 	}
1830*5113495bSYour Name 	vdev = target_if_spectral_get_vdev(spectral, smode);
1831*5113495bSYour Name 	if (!vdev)
1832*5113495bSYour Name 		return 0;
1833*5113495bSYour Name 
1834*5113495bSYour Name 	if (target_if_vdev_get_sec20chan_freq_mhz(vdev, &sec20chan_freq) < 0) {
1835*5113495bSYour Name 		wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
1836*5113495bSYour Name 		return 0;
1837*5113495bSYour Name 	}
1838*5113495bSYour Name 
1839*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
1840*5113495bSYour Name 
1841*5113495bSYour Name 	return sec20chan_freq;
1842*5113495bSYour Name }
1843*5113495bSYour Name 
1844*5113495bSYour Name /**
1845*5113495bSYour Name  * target_if_spectral_get_current_channel() - Get the current channel
1846*5113495bSYour Name  * @arg: Pointer to handle for Spectral target_if internal private data
1847*5113495bSYour Name  * @smode: Spectral scan mode
1848*5113495bSYour Name  *
1849*5113495bSYour Name  * Function to get the current channel (in MHz)
1850*5113495bSYour Name  *
1851*5113495bSYour Name  * Return: Current channel (in MHz) on success, 0 on failure
1852*5113495bSYour Name  */
1853*5113495bSYour Name uint32_t
target_if_spectral_get_current_channel(void * arg,enum spectral_scan_mode smode)1854*5113495bSYour Name target_if_spectral_get_current_channel(void *arg, enum spectral_scan_mode smode)
1855*5113495bSYour Name {
1856*5113495bSYour Name 	/*
1857*5113495bSYour Name 	 * XXX: Once we expand to use cases where Spectral could be activated
1858*5113495bSYour Name 	 * without a channel being set to VDEV, we need to consider returning a
1859*5113495bSYour Name 	 * negative value in case of failure and having all callers handle this.
1860*5113495bSYour Name 	 */
1861*5113495bSYour Name 
1862*5113495bSYour Name 	struct target_if_spectral *spectral = NULL;
1863*5113495bSYour Name 	int16_t chan_freq = 0;
1864*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev = NULL;
1865*5113495bSYour Name 
1866*5113495bSYour Name 	if (!arg) {
1867*5113495bSYour Name 		spectral_err("Null argument.");
1868*5113495bSYour Name 		return 0;
1869*5113495bSYour Name 	}
1870*5113495bSYour Name 
1871*5113495bSYour Name 	spectral = (struct target_if_spectral *)arg;
1872*5113495bSYour Name 
1873*5113495bSYour Name 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
1874*5113495bSYour Name 		spectral_err("Invalid Spectral mode %u", smode);
1875*5113495bSYour Name 		return 0;
1876*5113495bSYour Name 	}
1877*5113495bSYour Name 	vdev = target_if_spectral_get_vdev(spectral, smode);
1878*5113495bSYour Name 	if (!vdev)
1879*5113495bSYour Name 		return 0;
1880*5113495bSYour Name 
1881*5113495bSYour Name 	chan_freq = target_if_vdev_get_chan_freq(vdev);
1882*5113495bSYour Name 	if (chan_freq < 0) {
1883*5113495bSYour Name 		wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
1884*5113495bSYour Name 		return 0;
1885*5113495bSYour Name 	}
1886*5113495bSYour Name 
1887*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
1888*5113495bSYour Name 
1889*5113495bSYour Name 	return chan_freq;
1890*5113495bSYour Name }
1891*5113495bSYour Name 
1892*5113495bSYour Name /**
1893*5113495bSYour Name  * target_if_spectral_reset_hw() - Reset the hardware
1894*5113495bSYour Name  * @arg: Pointer to handle for Spectral target_if internal private data
1895*5113495bSYour Name  *
1896*5113495bSYour Name  * This is only a placeholder since it is not currently required in the offload
1897*5113495bSYour Name  * case.
1898*5113495bSYour Name  *
1899*5113495bSYour Name  * Return: 0
1900*5113495bSYour Name  */
1901*5113495bSYour Name uint32_t
target_if_spectral_reset_hw(void * arg)1902*5113495bSYour Name target_if_spectral_reset_hw(void *arg)
1903*5113495bSYour Name {
1904*5113495bSYour Name 	not_yet_implemented();
1905*5113495bSYour Name 	return 0;
1906*5113495bSYour Name }
1907*5113495bSYour Name 
1908*5113495bSYour Name /**
1909*5113495bSYour Name  * target_if_spectral_get_chain_noise_floor() - Get the Chain noise floor from
1910*5113495bSYour Name  * Noisefloor history buffer
1911*5113495bSYour Name  * @arg: Pointer to handle for Spectral target_if internal private data
1912*5113495bSYour Name  * @nf_buf: Pointer to buffer into which chain Noise Floor data should be copied
1913*5113495bSYour Name  *
1914*5113495bSYour Name  * This is only a placeholder since it is not currently required in the offload
1915*5113495bSYour Name  * case.
1916*5113495bSYour Name  *
1917*5113495bSYour Name  * Return: 0
1918*5113495bSYour Name  */
1919*5113495bSYour Name uint32_t
target_if_spectral_get_chain_noise_floor(void * arg,int16_t * nf_buf)1920*5113495bSYour Name target_if_spectral_get_chain_noise_floor(void *arg, int16_t *nf_buf)
1921*5113495bSYour Name {
1922*5113495bSYour Name 	not_yet_implemented();
1923*5113495bSYour Name 	return 0;
1924*5113495bSYour Name }
1925*5113495bSYour Name 
1926*5113495bSYour Name /**
1927*5113495bSYour Name  * target_if_spectral_get_ext_noisefloor() - Get the extension channel
1928*5113495bSYour Name  * noisefloor
1929*5113495bSYour Name  * @arg: Pointer to handle for Spectral target_if internal private data
1930*5113495bSYour Name  *
1931*5113495bSYour Name  * This is only a placeholder since it is not currently required in the offload
1932*5113495bSYour Name  * case.
1933*5113495bSYour Name  *
1934*5113495bSYour Name  * Return: 0
1935*5113495bSYour Name  */
1936*5113495bSYour Name int8_t
target_if_spectral_get_ext_noisefloor(void * arg)1937*5113495bSYour Name target_if_spectral_get_ext_noisefloor(void *arg)
1938*5113495bSYour Name {
1939*5113495bSYour Name 	not_yet_implemented();
1940*5113495bSYour Name 	return 0;
1941*5113495bSYour Name }
1942*5113495bSYour Name 
1943*5113495bSYour Name /**
1944*5113495bSYour Name  * target_if_spectral_get_ctl_noisefloor() - Get the control channel noisefloor
1945*5113495bSYour Name  * @arg: Pointer to handle for Spectral target_if internal private data
1946*5113495bSYour Name  *
1947*5113495bSYour Name  * This is only a placeholder since it is not currently required in the offload
1948*5113495bSYour Name  * case.
1949*5113495bSYour Name  *
1950*5113495bSYour Name  * Return: 0
1951*5113495bSYour Name  */
1952*5113495bSYour Name int8_t
target_if_spectral_get_ctl_noisefloor(void * arg)1953*5113495bSYour Name target_if_spectral_get_ctl_noisefloor(void *arg)
1954*5113495bSYour Name {
1955*5113495bSYour Name 	not_yet_implemented();
1956*5113495bSYour Name 	return 0;
1957*5113495bSYour Name }
1958*5113495bSYour Name 
1959*5113495bSYour Name /**
1960*5113495bSYour Name  * target_if_spectral_sops_configure_params() - Configure user supplied Spectral
1961*5113495bSYour Name  *                                         parameters
1962*5113495bSYour Name  * @arg: Pointer to handle for Spectral target_if internal private data
1963*5113495bSYour Name  * @params: Spectral parameters
1964*5113495bSYour Name  * @smode: Spectral scan mode
1965*5113495bSYour Name  *
1966*5113495bSYour Name  * Function to configure spectral parameters
1967*5113495bSYour Name  *
1968*5113495bSYour Name  * Return: 0 on success else failure
1969*5113495bSYour Name  */
1970*5113495bSYour Name uint32_t
target_if_spectral_sops_configure_params(void * arg,struct spectral_config * params,enum spectral_scan_mode smode)1971*5113495bSYour Name target_if_spectral_sops_configure_params(
1972*5113495bSYour Name 	void *arg, struct spectral_config *params,
1973*5113495bSYour Name 	enum spectral_scan_mode smode)
1974*5113495bSYour Name {
1975*5113495bSYour Name 	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
1976*5113495bSYour Name 
1977*5113495bSYour Name 	return target_if_spectral_info_write(
1978*5113495bSYour Name 		spectral,
1979*5113495bSYour Name 		smode,
1980*5113495bSYour Name 		TARGET_IF_SPECTRAL_INFO_PARAMS,
1981*5113495bSYour Name 		params, sizeof(*params));
1982*5113495bSYour Name }
1983*5113495bSYour Name 
1984*5113495bSYour Name /**
1985*5113495bSYour Name  * target_if_spectral_sops_get_params() - Get user configured Spectral
1986*5113495bSYour Name  * parameters
1987*5113495bSYour Name  * @arg: Pointer to handle for Spectral target_if internal private data
1988*5113495bSYour Name  * @params: Pointer to buffer into which Spectral parameters should be copied
1989*5113495bSYour Name  * @smode: Spectral scan mode
1990*5113495bSYour Name  *
1991*5113495bSYour Name  * Function to get the configured spectral parameters
1992*5113495bSYour Name  *
1993*5113495bSYour Name  * Return: 0 on success else failure
1994*5113495bSYour Name  */
1995*5113495bSYour Name uint32_t
target_if_spectral_sops_get_params(void * arg,struct spectral_config * params,enum spectral_scan_mode smode)1996*5113495bSYour Name target_if_spectral_sops_get_params(void *arg, struct spectral_config *params,
1997*5113495bSYour Name 				   enum spectral_scan_mode smode)
1998*5113495bSYour Name {
1999*5113495bSYour Name 	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
2000*5113495bSYour Name 
2001*5113495bSYour Name 	return target_if_spectral_info_read(
2002*5113495bSYour Name 		spectral,
2003*5113495bSYour Name 		smode,
2004*5113495bSYour Name 		TARGET_IF_SPECTRAL_INFO_PARAMS,
2005*5113495bSYour Name 		params, sizeof(*params));
2006*5113495bSYour Name }
2007*5113495bSYour Name 
2008*5113495bSYour Name /**
2009*5113495bSYour Name  * target_if_spectral_get_ent_mask() - Get enterprise mask
2010*5113495bSYour Name  * @arg: Pointer to handle for Spectral target_if internal private data
2011*5113495bSYour Name  *
2012*5113495bSYour Name  * This is only a placeholder since it is not currently required in the offload
2013*5113495bSYour Name  * case.
2014*5113495bSYour Name  *
2015*5113495bSYour Name  * Return: 0
2016*5113495bSYour Name  */
2017*5113495bSYour Name static uint32_t
target_if_spectral_get_ent_mask(void * arg)2018*5113495bSYour Name target_if_spectral_get_ent_mask(void *arg)
2019*5113495bSYour Name {
2020*5113495bSYour Name 	not_yet_implemented();
2021*5113495bSYour Name 	return 0;
2022*5113495bSYour Name }
2023*5113495bSYour Name 
2024*5113495bSYour Name /**
2025*5113495bSYour Name  * target_if_spectral_get_macaddr() - Get radio MAC address
2026*5113495bSYour Name  * @arg: Pointer to handle for Spectral target_if internal private data
2027*5113495bSYour Name  * @addr: Pointer to buffer into which MAC address should be copied
2028*5113495bSYour Name  *
2029*5113495bSYour Name  * Function to get the MAC address of the pdev
2030*5113495bSYour Name  *
2031*5113495bSYour Name  * Return: 0 on success, -1 on failure
2032*5113495bSYour Name  */
2033*5113495bSYour Name static uint32_t
target_if_spectral_get_macaddr(void * arg,char * addr)2034*5113495bSYour Name target_if_spectral_get_macaddr(void *arg, char *addr)
2035*5113495bSYour Name {
2036*5113495bSYour Name 	uint8_t *myaddr = NULL;
2037*5113495bSYour Name 	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
2038*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev = NULL;
2039*5113495bSYour Name 
2040*5113495bSYour Name 	pdev = spectral->pdev_obj;
2041*5113495bSYour Name 
2042*5113495bSYour Name 	wlan_pdev_obj_lock(pdev);
2043*5113495bSYour Name 	myaddr = wlan_pdev_get_hw_macaddr(pdev);
2044*5113495bSYour Name 	wlan_pdev_obj_unlock(pdev);
2045*5113495bSYour Name 	qdf_mem_copy(addr, myaddr, QDF_MAC_ADDR_SIZE);
2046*5113495bSYour Name 
2047*5113495bSYour Name 	return 0;
2048*5113495bSYour Name }
2049*5113495bSYour Name 
2050*5113495bSYour Name /**
2051*5113495bSYour Name  * target_if_init_spectral_param_min_max_be() - Initialize Spectral parameter
2052*5113495bSYour Name  * min and max values for beryllium chipsets
2053*5113495bSYour Name  *
2054*5113495bSYour Name  * @spectral: Spectral LMAC object
2055*5113495bSYour Name  *
2056*5113495bSYour Name  * Return: QDF_STATUS of operation
2057*5113495bSYour Name  */
2058*5113495bSYour Name static QDF_STATUS
target_if_init_spectral_param_min_max_be(struct target_if_spectral * spectral)2059*5113495bSYour Name target_if_init_spectral_param_min_max_be(struct target_if_spectral *spectral)
2060*5113495bSYour Name {
2061*5113495bSYour Name 	struct spectral_param_min_max *param_min_max;
2062*5113495bSYour Name 	enum phy_ch_width op_bw;
2063*5113495bSYour Name 	QDF_STATUS status;
2064*5113495bSYour Name 
2065*5113495bSYour Name 	param_min_max = &spectral->param_min_max;
2066*5113495bSYour Name 	param_min_max->fft_size_min = SPECTRAL_PARAM_FFT_SIZE_MIN_GEN3_BE;
2067*5113495bSYour Name 	param_min_max->scan_count_max = SPECTRAL_PARAM_SCAN_COUNT_MAX_GEN3_BE;
2068*5113495bSYour Name 
2069*5113495bSYour Name 	for (op_bw = CH_WIDTH_20MHZ; op_bw < CH_WIDTH_MAX; op_bw++) {
2070*5113495bSYour Name 		bool is_supported;
2071*5113495bSYour Name 
2072*5113495bSYour Name 		status = wlan_reg_is_chwidth_supported(spectral->pdev_obj,
2073*5113495bSYour Name 						       op_bw, &is_supported);
2074*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
2075*5113495bSYour Name 			spectral_err("Unable to check if ch_width(%d) is supported",
2076*5113495bSYour Name 				     op_bw);
2077*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
2078*5113495bSYour Name 		}
2079*5113495bSYour Name 
2080*5113495bSYour Name 		if (!is_supported) {
2081*5113495bSYour Name 			param_min_max->fft_size_max[op_bw] = INVALID_FFT_SIZE;
2082*5113495bSYour Name 			continue;
2083*5113495bSYour Name 		}
2084*5113495bSYour Name 
2085*5113495bSYour Name 		switch (op_bw) {
2086*5113495bSYour Name 		case CH_WIDTH_20MHZ:
2087*5113495bSYour Name 			param_min_max->fft_size_max[op_bw] =
2088*5113495bSYour Name 				SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_BE_20MHZ;
2089*5113495bSYour Name 			break;
2090*5113495bSYour Name 
2091*5113495bSYour Name 		case CH_WIDTH_40MHZ:
2092*5113495bSYour Name 			param_min_max->fft_size_max[op_bw] =
2093*5113495bSYour Name 				SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_BE_40MHZ;
2094*5113495bSYour Name 			break;
2095*5113495bSYour Name 
2096*5113495bSYour Name 		default:
2097*5113495bSYour Name 			param_min_max->fft_size_max[op_bw] =
2098*5113495bSYour Name 				SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_BE;
2099*5113495bSYour Name 		}
2100*5113495bSYour Name 	}
2101*5113495bSYour Name 
2102*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
2103*5113495bSYour Name }
2104*5113495bSYour Name 
2105*5113495bSYour Name /**
2106*5113495bSYour Name  * target_if_init_spectral_param_min_max() - Initialize Spectral parameter
2107*5113495bSYour Name  * min and max values
2108*5113495bSYour Name  *
2109*5113495bSYour Name  * @spectral: Spectral LMAC object
2110*5113495bSYour Name  * @gen: Spectral HW generation
2111*5113495bSYour Name  * @target_type: Target type
2112*5113495bSYour Name  *
2113*5113495bSYour Name  * Initialize Spectral parameter min and max values
2114*5113495bSYour Name  *
2115*5113495bSYour Name  * Return: QDF_STATUS
2116*5113495bSYour Name  */
2117*5113495bSYour Name static QDF_STATUS
target_if_init_spectral_param_min_max(struct target_if_spectral * spectral,enum spectral_gen gen,uint32_t target_type)2118*5113495bSYour Name target_if_init_spectral_param_min_max(
2119*5113495bSYour Name 				struct target_if_spectral *spectral,
2120*5113495bSYour Name 				enum spectral_gen gen, uint32_t target_type)
2121*5113495bSYour Name {
2122*5113495bSYour Name 	struct spectral_param_min_max *param_min_max;
2123*5113495bSYour Name 
2124*5113495bSYour Name 	if (!spectral) {
2125*5113495bSYour Name 		spectral_err("Spectral LMAC object is null");
2126*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
2127*5113495bSYour Name 	}
2128*5113495bSYour Name 
2129*5113495bSYour Name 	if (is_spectral_arch_beryllium(target_type))
2130*5113495bSYour Name 		return target_if_init_spectral_param_min_max_be(spectral);
2131*5113495bSYour Name 
2132*5113495bSYour Name 	param_min_max = &spectral->param_min_max;
2133*5113495bSYour Name 	switch (gen) {
2134*5113495bSYour Name 	case SPECTRAL_GEN3:
2135*5113495bSYour Name 		param_min_max->fft_size_min = SPECTRAL_PARAM_FFT_SIZE_MIN_GEN3;
2136*5113495bSYour Name 		param_min_max->fft_size_max[CH_WIDTH_20MHZ] =
2137*5113495bSYour Name 				SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT;
2138*5113495bSYour Name 		param_min_max->scan_count_max =
2139*5113495bSYour Name 				SPECTRAL_PARAM_SCAN_COUNT_MAX_GEN3;
2140*5113495bSYour Name 		if (target_type == TARGET_TYPE_QCN9000 ||
2141*5113495bSYour Name 		    target_type == TARGET_TYPE_QCN6122 ||
2142*5113495bSYour Name 		    target_type == TARGET_TYPE_QCN9160 ||
2143*5113495bSYour Name 		    target_type == TARGET_TYPE_QCA5018 ||
2144*5113495bSYour Name 		    target_type == TARGET_TYPE_QCA6490 ||
2145*5113495bSYour Name 		    target_type == TARGET_TYPE_KIWI ||
2146*5113495bSYour Name 		    target_type == TARGET_TYPE_MANGO ||
2147*5113495bSYour Name 		    target_type == TARGET_TYPE_PEACH) {
2148*5113495bSYour Name 			param_min_max->fft_size_max[CH_WIDTH_40MHZ] =
2149*5113495bSYour Name 				SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000;
2150*5113495bSYour Name 			param_min_max->fft_size_max[CH_WIDTH_80MHZ] =
2151*5113495bSYour Name 				SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000;
2152*5113495bSYour Name 			param_min_max->fft_size_max[CH_WIDTH_160MHZ] =
2153*5113495bSYour Name 				SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000;
2154*5113495bSYour Name 			param_min_max->fft_size_max[CH_WIDTH_80P80MHZ] =
2155*5113495bSYour Name 				SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000;
2156*5113495bSYour Name 		} else {
2157*5113495bSYour Name 			param_min_max->fft_size_max[CH_WIDTH_40MHZ] =
2158*5113495bSYour Name 				SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT;
2159*5113495bSYour Name 			param_min_max->fft_size_max[CH_WIDTH_80MHZ] =
2160*5113495bSYour Name 				SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT;
2161*5113495bSYour Name 			param_min_max->fft_size_max[CH_WIDTH_160MHZ] =
2162*5113495bSYour Name 				SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT;
2163*5113495bSYour Name 			param_min_max->fft_size_max[CH_WIDTH_80P80MHZ] =
2164*5113495bSYour Name 				SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT;
2165*5113495bSYour Name 		}
2166*5113495bSYour Name 		break;
2167*5113495bSYour Name 
2168*5113495bSYour Name 	case SPECTRAL_GEN2:
2169*5113495bSYour Name 		param_min_max->fft_size_min = SPECTRAL_PARAM_FFT_SIZE_MIN_GEN2;
2170*5113495bSYour Name 		param_min_max->fft_size_max[CH_WIDTH_20MHZ] =
2171*5113495bSYour Name 					SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2;
2172*5113495bSYour Name 		param_min_max->fft_size_max[CH_WIDTH_40MHZ] =
2173*5113495bSYour Name 					SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2;
2174*5113495bSYour Name 		param_min_max->fft_size_max[CH_WIDTH_80MHZ] =
2175*5113495bSYour Name 					SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2;
2176*5113495bSYour Name 		param_min_max->fft_size_max[CH_WIDTH_80P80MHZ] =
2177*5113495bSYour Name 					SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2;
2178*5113495bSYour Name 		param_min_max->fft_size_max[CH_WIDTH_160MHZ] =
2179*5113495bSYour Name 					SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2;
2180*5113495bSYour Name 		break;
2181*5113495bSYour Name 
2182*5113495bSYour Name 	default:
2183*5113495bSYour Name 		spectral_err("Invalid spectral generation %d", gen);
2184*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
2185*5113495bSYour Name 	}
2186*5113495bSYour Name 
2187*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
2188*5113495bSYour Name }
2189*5113495bSYour Name 
2190*5113495bSYour Name /**
2191*5113495bSYour Name  * target_if_init_spectral_param_properties() - Initialize Spectral parameter
2192*5113495bSYour Name  *                                              properties
2193*5113495bSYour Name  * @spectral: Pointer to Spectral target_if internal private data
2194*5113495bSYour Name  *
2195*5113495bSYour Name  * Initialize Spectral parameter properties
2196*5113495bSYour Name  *
2197*5113495bSYour Name  * Return: QDF_STATUS
2198*5113495bSYour Name  */
2199*5113495bSYour Name static QDF_STATUS
target_if_init_spectral_param_properties(struct target_if_spectral * spectral)2200*5113495bSYour Name target_if_init_spectral_param_properties(struct target_if_spectral *spectral)
2201*5113495bSYour Name {
2202*5113495bSYour Name 	enum spectral_scan_mode smode = SPECTRAL_SCAN_MODE_NORMAL;
2203*5113495bSYour Name 	int param;
2204*5113495bSYour Name 
2205*5113495bSYour Name 	/* Initialize default values for properties.
2206*5113495bSYour Name 	 * Default values are supported for all the parameters for all modes
2207*5113495bSYour Name 	 * and allows different values for each mode for all the parameters .
2208*5113495bSYour Name 	 */
2209*5113495bSYour Name 	for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) {
2210*5113495bSYour Name 		for (param = 0; param < SPECTRAL_PARAM_MAX; param++) {
2211*5113495bSYour Name 			spectral->properties[smode][param].supported = true;
2212*5113495bSYour Name 			spectral->properties[smode][param].common_all_modes =
2213*5113495bSYour Name 									false;
2214*5113495bSYour Name 		}
2215*5113495bSYour Name 	}
2216*5113495bSYour Name 
2217*5113495bSYour Name 	/* Once FW advertisement is in place remove this hard coding */
2218*5113495bSYour Name 	smode = SPECTRAL_SCAN_MODE_NORMAL;
2219*5113495bSYour Name 	spectral->properties[SPECTRAL_SCAN_MODE_NORMAL]
2220*5113495bSYour Name 			[SPECTRAL_PARAM_FREQUENCY].supported = false;
2221*5113495bSYour Name 	for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) {
2222*5113495bSYour Name 		spectral->properties[smode]
2223*5113495bSYour Name 			[SPECTRAL_PARAM_SPECT_PRI].common_all_modes = true;
2224*5113495bSYour Name 		spectral->properties[smode]
2225*5113495bSYour Name 			[SPECTRAL_PARAM_SCAN_PERIOD].common_all_modes = true;
2226*5113495bSYour Name 		spectral->properties[smode]
2227*5113495bSYour Name 			[SPECTRAL_PARAM_INIT_DELAY].common_all_modes = true;
2228*5113495bSYour Name 	}
2229*5113495bSYour Name 
2230*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
2231*5113495bSYour Name }
2232*5113495bSYour Name 
2233*5113495bSYour Name /* Bandwidth to half bandwidth mapping */
2234*5113495bSYour Name static const enum phy_ch_width half_bw_map[] = {
2235*5113495bSYour Name #ifdef WLAN_FEATURE_11BE
2236*5113495bSYour Name 	[CH_WIDTH_320MHZ] = CH_WIDTH_160MHZ,
2237*5113495bSYour Name #endif
2238*5113495bSYour Name 	[CH_WIDTH_80P80MHZ] = CH_WIDTH_80MHZ,
2239*5113495bSYour Name 	[CH_WIDTH_160MHZ] = CH_WIDTH_80MHZ,
2240*5113495bSYour Name 	[CH_WIDTH_80MHZ] = CH_WIDTH_40MHZ,
2241*5113495bSYour Name 	[CH_WIDTH_40MHZ] = CH_WIDTH_20MHZ,
2242*5113495bSYour Name 	[CH_WIDTH_20MHZ] = CH_WIDTH_10MHZ,
2243*5113495bSYour Name 	[CH_WIDTH_10MHZ] = CH_WIDTH_5MHZ,
2244*5113495bSYour Name 	[CH_WIDTH_5MHZ] = CH_WIDTH_INVALID
2245*5113495bSYour Name };
2246*5113495bSYour Name 
2247*5113495bSYour Name /**
2248*5113495bSYour Name  * target_if_get_half_bandwidth() - Get half bandwidth for a given bandwidth
2249*5113495bSYour Name  * @bw: bandwidth
2250*5113495bSYour Name  *
2251*5113495bSYour Name  * Return: Half bandwidth of @bw
2252*5113495bSYour Name  */
target_if_get_half_bandwidth(enum phy_ch_width bw)2253*5113495bSYour Name static enum phy_ch_width target_if_get_half_bandwidth(enum phy_ch_width bw)
2254*5113495bSYour Name {
2255*5113495bSYour Name 	if (bw >= CH_WIDTH_INVALID)
2256*5113495bSYour Name 		return CH_WIDTH_INVALID;
2257*5113495bSYour Name 
2258*5113495bSYour Name 	return half_bw_map[bw];
2259*5113495bSYour Name }
2260*5113495bSYour Name 
2261*5113495bSYour Name /**
2262*5113495bSYour Name  * target_if_populate_supported_sscan_bws_be() - Populate supported spectral
2263*5113495bSYour Name  * scan bandwidths for beryllium chipsets
2264*5113495bSYour Name  * @spectral: Spectral LMAC object
2265*5113495bSYour Name  *
2266*5113495bSYour Name  * Return: QDF_STATUS of operation
2267*5113495bSYour Name  */
2268*5113495bSYour Name static QDF_STATUS
target_if_populate_supported_sscan_bws_be(struct target_if_spectral * spectral)2269*5113495bSYour Name target_if_populate_supported_sscan_bws_be(struct target_if_spectral *spectral)
2270*5113495bSYour Name {
2271*5113495bSYour Name 	enum phy_ch_width op_bw;
2272*5113495bSYour Name 	struct spectral_supported_bws *supported_bws;
2273*5113495bSYour Name 	QDF_STATUS status;
2274*5113495bSYour Name 
2275*5113495bSYour Name 	if (!spectral) {
2276*5113495bSYour Name 		spectral_err("spectral variable is null");
2277*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
2278*5113495bSYour Name 	}
2279*5113495bSYour Name 
2280*5113495bSYour Name 	/* 20MHz */
2281*5113495bSYour Name 	op_bw = CH_WIDTH_20MHZ;
2282*5113495bSYour Name 	supported_bws = &spectral->supported_bws
2283*5113495bSYour Name 			[SPECTRAL_SCAN_MODE_NORMAL][op_bw];
2284*5113495bSYour Name 	supported_bws->bandwidths |= 1 << get_supported_sscan_bw_pos(op_bw);
2285*5113495bSYour Name 	spectral->supported_sscan_bw_list
2286*5113495bSYour Name 		[SPECTRAL_SCAN_MODE_NORMAL][op_bw] = true;
2287*5113495bSYour Name 	supported_bws = &spectral->supported_bws
2288*5113495bSYour Name 			[SPECTRAL_SCAN_MODE_AGILE][op_bw];
2289*5113495bSYour Name 	supported_bws->bandwidths |= 1 << get_supported_sscan_bw_pos(op_bw);
2290*5113495bSYour Name 	spectral->supported_sscan_bw_list
2291*5113495bSYour Name 		[SPECTRAL_SCAN_MODE_AGILE][op_bw] = true;
2292*5113495bSYour Name 
2293*5113495bSYour Name 	for (op_bw = CH_WIDTH_40MHZ; op_bw < CH_WIDTH_MAX; op_bw++) {
2294*5113495bSYour Name 		bool is_supported;
2295*5113495bSYour Name 		enum phy_ch_width half_op_bw;
2296*5113495bSYour Name 
2297*5113495bSYour Name 		status = wlan_reg_is_chwidth_supported(spectral->pdev_obj,
2298*5113495bSYour Name 						       op_bw, &is_supported);
2299*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
2300*5113495bSYour Name 			spectral_err("Unable to check if ch_width(%d) is supported",
2301*5113495bSYour Name 				     op_bw);
2302*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
2303*5113495bSYour Name 		}
2304*5113495bSYour Name 
2305*5113495bSYour Name 		if (!is_supported)
2306*5113495bSYour Name 			continue;
2307*5113495bSYour Name 
2308*5113495bSYour Name 		spectral_debug("Updating supported bw for op_bw: %d", op_bw);
2309*5113495bSYour Name 		/* Normal mode */
2310*5113495bSYour Name 		supported_bws = &spectral->supported_bws
2311*5113495bSYour Name 				[SPECTRAL_SCAN_MODE_NORMAL][op_bw];
2312*5113495bSYour Name 		supported_bws->bandwidths |=
2313*5113495bSYour Name 				1 << get_supported_sscan_bw_pos(op_bw);
2314*5113495bSYour Name 		spectral->supported_sscan_bw_list
2315*5113495bSYour Name 			[SPECTRAL_SCAN_MODE_NORMAL][op_bw] = true;
2316*5113495bSYour Name 
2317*5113495bSYour Name 		/* Agile mode */
2318*5113495bSYour Name 		supported_bws = &spectral->supported_bws
2319*5113495bSYour Name 				[SPECTRAL_SCAN_MODE_AGILE][op_bw];
2320*5113495bSYour Name 		supported_bws->bandwidths |=
2321*5113495bSYour Name 				1 << get_supported_sscan_bw_pos(op_bw);
2322*5113495bSYour Name 		spectral->supported_sscan_bw_list
2323*5113495bSYour Name 			[SPECTRAL_SCAN_MODE_AGILE][op_bw] = true;
2324*5113495bSYour Name 
2325*5113495bSYour Name 		half_op_bw = target_if_get_half_bandwidth(op_bw);
2326*5113495bSYour Name 		if (half_op_bw != CH_WIDTH_INVALID) {
2327*5113495bSYour Name 			supported_bws->bandwidths |=
2328*5113495bSYour Name 				1 << get_supported_sscan_bw_pos(half_op_bw);
2329*5113495bSYour Name 			spectral->supported_sscan_bw_list
2330*5113495bSYour Name 				[SPECTRAL_SCAN_MODE_AGILE][half_op_bw] = true;
2331*5113495bSYour Name 		}
2332*5113495bSYour Name 	}
2333*5113495bSYour Name 
2334*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
2335*5113495bSYour Name }
2336*5113495bSYour Name 
2337*5113495bSYour Name /**
2338*5113495bSYour Name  * target_if_populate_supported_sscan_bws() - Populate supported spectral
2339*5113495bSYour Name  * scan bandwidths
2340*5113495bSYour Name  * @spectral: Spectral LMAC object
2341*5113495bSYour Name  * @target_type: Target type
2342*5113495bSYour Name  *
2343*5113495bSYour Name  * Return: QDF_STATUS of operation
2344*5113495bSYour Name  */
2345*5113495bSYour Name static QDF_STATUS
target_if_populate_supported_sscan_bws(struct target_if_spectral * spectral,uint32_t target_type)2346*5113495bSYour Name target_if_populate_supported_sscan_bws(struct target_if_spectral *spectral,
2347*5113495bSYour Name 				       uint32_t target_type)
2348*5113495bSYour Name {
2349*5113495bSYour Name 	enum spectral_scan_mode smode;
2350*5113495bSYour Name 	enum phy_ch_width op_bw;
2351*5113495bSYour Name 	struct spectral_supported_bws *supported_bws;
2352*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
2353*5113495bSYour Name 	QDF_STATUS status;
2354*5113495bSYour Name 
2355*5113495bSYour Name 	if (!spectral) {
2356*5113495bSYour Name 		spectral_err("spectral is null");
2357*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
2358*5113495bSYour Name 	}
2359*5113495bSYour Name 
2360*5113495bSYour Name 	if (is_spectral_arch_beryllium(target_type))
2361*5113495bSYour Name 		return target_if_populate_supported_sscan_bws_be(spectral);
2362*5113495bSYour Name 
2363*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(spectral->pdev_obj);
2364*5113495bSYour Name 	if (!psoc) {
2365*5113495bSYour Name 		spectral_err("psoc is null");
2366*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
2367*5113495bSYour Name 	}
2368*5113495bSYour Name 
2369*5113495bSYour Name 	for (op_bw = CH_WIDTH_20MHZ; op_bw < CH_WIDTH_MAX; op_bw++) {
2370*5113495bSYour Name 		bool is_supported;
2371*5113495bSYour Name 
2372*5113495bSYour Name 		status = wlan_reg_is_chwidth_supported(spectral->pdev_obj,
2373*5113495bSYour Name 						       op_bw, &is_supported);
2374*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
2375*5113495bSYour Name 			spectral_err("Unable to check if ch_width(%d) is supported",
2376*5113495bSYour Name 				     op_bw);
2377*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
2378*5113495bSYour Name 		}
2379*5113495bSYour Name 
2380*5113495bSYour Name 		if (!is_supported)
2381*5113495bSYour Name 			continue;
2382*5113495bSYour Name 
2383*5113495bSYour Name 		spectral_debug("Updating supported bw for op_bw: %d", op_bw);
2384*5113495bSYour Name 		smode = SPECTRAL_SCAN_MODE_NORMAL;
2385*5113495bSYour Name 		for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) {
2386*5113495bSYour Name 			supported_bws = &spectral->supported_bws[smode][op_bw];
2387*5113495bSYour Name 
2388*5113495bSYour Name 			if (is_ch_width_160_or_80p80(op_bw) &&
2389*5113495bSYour Name 			    smode == SPECTRAL_SCAN_MODE_AGILE) {
2390*5113495bSYour Name 				/**
2391*5113495bSYour Name 				 * If fragmentation is supported, then only 80Hz
2392*5113495bSYour Name 				 * agile width is supported
2393*5113495bSYour Name 				 */
2394*5113495bSYour Name 				if (spectral->rparams.
2395*5113495bSYour Name 				    fragmentation_160[smode]) {
2396*5113495bSYour Name 					supported_bws->bandwidths |=
2397*5113495bSYour Name 					 1 << get_supported_sscan_bw_pos(
2398*5113495bSYour Name 						CH_WIDTH_80MHZ);
2399*5113495bSYour Name 					spectral->supported_sscan_bw_list
2400*5113495bSYour Name 						[smode][CH_WIDTH_80MHZ] = true;
2401*5113495bSYour Name 				}
2402*5113495bSYour Name 
2403*5113495bSYour Name 				/**
2404*5113495bSYour Name 				 * If restricted 80p80 is supported, then both
2405*5113495bSYour Name 				 * 160 and 80p80 agile widths are supported for
2406*5113495bSYour Name 				 * 160MHz, and only 160MHz agile width is
2407*5113495bSYour Name 				 * supported for 80p80
2408*5113495bSYour Name 				 */
2409*5113495bSYour Name 				if (wlan_psoc_nif_fw_ext_cap_get(
2410*5113495bSYour Name 				     psoc, WLAN_SOC_RESTRICTED_80P80_SUPPORT)) {
2411*5113495bSYour Name 					supported_bws->bandwidths |=
2412*5113495bSYour Name 						1 << get_supported_sscan_bw_pos(
2413*5113495bSYour Name 							CH_WIDTH_160MHZ);
2414*5113495bSYour Name 					spectral->supported_sscan_bw_list
2415*5113495bSYour Name 						[smode][CH_WIDTH_160MHZ] = true;
2416*5113495bSYour Name 
2417*5113495bSYour Name 					if (op_bw == CH_WIDTH_160MHZ) {
2418*5113495bSYour Name 						supported_bws->bandwidths |=
2419*5113495bSYour Name 						1 << get_supported_sscan_bw_pos(
2420*5113495bSYour Name 							CH_WIDTH_80P80MHZ);
2421*5113495bSYour Name 						spectral->supported_sscan_bw_list
2422*5113495bSYour Name 							[smode][CH_WIDTH_80P80MHZ] = true;
2423*5113495bSYour Name 					}
2424*5113495bSYour Name 				}
2425*5113495bSYour Name 			} else {
2426*5113495bSYour Name 				supported_bws->bandwidths |=
2427*5113495bSYour Name 					1 << get_supported_sscan_bw_pos(
2428*5113495bSYour Name 						op_bw);
2429*5113495bSYour Name 					spectral->supported_sscan_bw_list
2430*5113495bSYour Name 						[smode][op_bw] = true;
2431*5113495bSYour Name 			}
2432*5113495bSYour Name 		}
2433*5113495bSYour Name 	}
2434*5113495bSYour Name 
2435*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
2436*5113495bSYour Name }
2437*5113495bSYour Name 
2438*5113495bSYour Name QDF_STATUS
target_if_init_spectral_capability(struct target_if_spectral * spectral,uint32_t target_type)2439*5113495bSYour Name target_if_init_spectral_capability(struct target_if_spectral *spectral,
2440*5113495bSYour Name 				   uint32_t target_type)
2441*5113495bSYour Name {
2442*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
2443*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev;
2444*5113495bSYour Name 	struct wlan_psoc_host_spectral_scaling_params *scaling_params;
2445*5113495bSYour Name 	uint8_t num_bin_scaling_params, param_idx, pdev_id;
2446*5113495bSYour Name 	struct target_psoc_info *tgt_psoc_info;
2447*5113495bSYour Name 	struct wlan_psoc_host_service_ext_param *ext_svc_param;
2448*5113495bSYour Name 	struct spectral_caps *pcap = &spectral->capability;
2449*5113495bSYour Name 	QDF_STATUS status;
2450*5113495bSYour Name 
2451*5113495bSYour Name 	pdev = spectral->pdev_obj;
2452*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
2453*5113495bSYour Name 	if (!psoc) {
2454*5113495bSYour Name 		spectral_err("psoc is null");
2455*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
2456*5113495bSYour Name 	}
2457*5113495bSYour Name 
2458*5113495bSYour Name 	tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc);
2459*5113495bSYour Name 	if (!tgt_psoc_info) {
2460*5113495bSYour Name 		spectral_err("target_psoc_info is null");
2461*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
2462*5113495bSYour Name 	}
2463*5113495bSYour Name 
2464*5113495bSYour Name 	ext_svc_param = target_psoc_get_service_ext_param(tgt_psoc_info);
2465*5113495bSYour Name 	num_bin_scaling_params = ext_svc_param->num_bin_scaling_params;
2466*5113495bSYour Name 	scaling_params = target_psoc_get_spectral_scaling_params(tgt_psoc_info);
2467*5113495bSYour Name 	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
2468*5113495bSYour Name 
2469*5113495bSYour Name 	/* XXX : Workaround: Set Spectral capability */
2470*5113495bSYour Name 	pcap = &spectral->capability;
2471*5113495bSYour Name 	pcap->phydiag_cap = 1;
2472*5113495bSYour Name 	pcap->radar_cap = 1;
2473*5113495bSYour Name 	pcap->spectral_cap = wlan_pdev_nif_feat_ext_cap_get(
2474*5113495bSYour Name 			pdev, WLAN_PDEV_FEXT_NORMAL_SPECTRAL_SCAN_DIS);
2475*5113495bSYour Name 	pcap->advncd_spectral_cap = pcap->spectral_cap;
2476*5113495bSYour Name 	pcap->hw_gen = spectral->spectral_gen;
2477*5113495bSYour Name 
2478*5113495bSYour Name 	pcap->agile_spectral_cap = !wlan_pdev_nif_feat_ext_cap_get(
2479*5113495bSYour Name 			pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_DIS);
2480*5113495bSYour Name 	pcap->agile_spectral_cap_160 = !wlan_pdev_nif_feat_ext_cap_get(
2481*5113495bSYour Name 			pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_160_DIS);
2482*5113495bSYour Name 	pcap->agile_spectral_cap_80p80 = !wlan_pdev_nif_feat_ext_cap_get(
2483*5113495bSYour Name 			pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_80P80_DIS);
2484*5113495bSYour Name 	pcap->agile_spectral_cap_320 = !wlan_pdev_nif_feat_ext_cap_get(
2485*5113495bSYour Name 			pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_320_DIS);
2486*5113495bSYour Name 
2487*5113495bSYour Name 	if (scaling_params) {
2488*5113495bSYour Name 		for (param_idx = 0; param_idx < num_bin_scaling_params;
2489*5113495bSYour Name 		     param_idx++) {
2490*5113495bSYour Name 			if (scaling_params[param_idx].pdev_id == pdev_id) {
2491*5113495bSYour Name 				pcap->is_scaling_params_populated = true;
2492*5113495bSYour Name 				pcap->formula_id =
2493*5113495bSYour Name 				    scaling_params[param_idx].formula_id;
2494*5113495bSYour Name 				pcap->low_level_offset =
2495*5113495bSYour Name 				    scaling_params[param_idx].low_level_offset;
2496*5113495bSYour Name 				pcap->high_level_offset =
2497*5113495bSYour Name 				    scaling_params[param_idx].high_level_offset;
2498*5113495bSYour Name 				pcap->rssi_thr =
2499*5113495bSYour Name 				    scaling_params[param_idx].rssi_thr;
2500*5113495bSYour Name 				pcap->default_agc_max_gain =
2501*5113495bSYour Name 				 scaling_params[param_idx].default_agc_max_gain;
2502*5113495bSYour Name 				break;
2503*5113495bSYour Name 			}
2504*5113495bSYour Name 		}
2505*5113495bSYour Name 	}
2506*5113495bSYour Name 
2507*5113495bSYour Name 	pcap->num_detectors_20mhz = 1;
2508*5113495bSYour Name 	pcap->num_detectors_40mhz = 1;
2509*5113495bSYour Name 	pcap->num_detectors_80mhz = 1;
2510*5113495bSYour Name 	if (target_type == TARGET_TYPE_QCN9000 ||
2511*5113495bSYour Name 	    target_type == TARGET_TYPE_QCN6122 ||
2512*5113495bSYour Name 	    target_type == TARGET_TYPE_QCN9160 ||
2513*5113495bSYour Name 	    target_type == TARGET_TYPE_QCA6490 ||
2514*5113495bSYour Name 	    target_type == TARGET_TYPE_KIWI ||
2515*5113495bSYour Name 	    target_type == TARGET_TYPE_MANGO ||
2516*5113495bSYour Name 	    target_type == TARGET_TYPE_PEACH) {
2517*5113495bSYour Name 		pcap->num_detectors_160mhz = 1;
2518*5113495bSYour Name 		pcap->num_detectors_80p80mhz = 1;
2519*5113495bSYour Name 		pcap->num_detectors_320mhz = 0;
2520*5113495bSYour Name 	} else if (is_spectral_arch_beryllium(target_type)) {
2521*5113495bSYour Name 		pcap->num_detectors_160mhz = 1;
2522*5113495bSYour Name 		pcap->num_detectors_80p80mhz = 0;
2523*5113495bSYour Name 		pcap->num_detectors_320mhz = 1;
2524*5113495bSYour Name 	} else {
2525*5113495bSYour Name 		pcap->num_detectors_160mhz = 2;
2526*5113495bSYour Name 		pcap->num_detectors_80p80mhz = 2;
2527*5113495bSYour Name 		pcap->num_detectors_320mhz = 0;
2528*5113495bSYour Name 	}
2529*5113495bSYour Name 
2530*5113495bSYour Name 	status = target_if_populate_supported_sscan_bws(spectral, target_type);
2531*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
2532*5113495bSYour Name 		spectral_err("Unable to populate supported sscan BWs");
2533*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
2534*5113495bSYour Name 	}
2535*5113495bSYour Name 
2536*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
2537*5113495bSYour Name }
2538*5113495bSYour Name 
2539*5113495bSYour Name #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION
2540*5113495bSYour Name /**
2541*5113495bSYour Name  * target_if_init_spectral_simulation_ops() - Initialize spectral target_if
2542*5113495bSYour Name  * internal operations with functions related to spectral simulation
2543*5113495bSYour Name  * @p_sops: spectral low level ops table
2544*5113495bSYour Name  *
2545*5113495bSYour Name  * Initialize spectral target_if internal operations with functions
2546*5113495bSYour Name  * related to spectral simulation
2547*5113495bSYour Name  *
2548*5113495bSYour Name  * Return: None
2549*5113495bSYour Name  */
2550*5113495bSYour Name static void
target_if_init_spectral_simulation_ops(struct target_if_spectral_ops * p_sops)2551*5113495bSYour Name target_if_init_spectral_simulation_ops(struct target_if_spectral_ops *p_sops)
2552*5113495bSYour Name {
2553*5113495bSYour Name 	/*
2554*5113495bSYour Name 	 * Spectral simulation is currently intended for platform transitions
2555*5113495bSYour Name 	 * where underlying HW support may not be available for some time.
2556*5113495bSYour Name 	 * Hence, we do not currently provide a runtime switch to turn the
2557*5113495bSYour Name 	 * simulation on or off.
2558*5113495bSYour Name 	 * In case of future requirements where runtime switches are required,
2559*5113495bSYour Name 	 * this can be added. But it is suggested to use application layer
2560*5113495bSYour Name 	 * simulation as far as possible in such cases, since the main
2561*5113495bSYour Name 	 * use of record and replay of samples would concern higher
2562*5113495bSYour Name 	 * level sample processing rather than lower level delivery.
2563*5113495bSYour Name 	 */
2564*5113495bSYour Name 	p_sops->is_spectral_enabled = target_if_spectral_sops_sim_is_enabled;
2565*5113495bSYour Name 	p_sops->is_spectral_active = target_if_spectral_sops_sim_is_active;
2566*5113495bSYour Name 	p_sops->start_spectral_scan = target_if_spectral_sops_sim_start_scan;
2567*5113495bSYour Name 	p_sops->stop_spectral_scan = target_if_spectral_sops_sim_stop_scan;
2568*5113495bSYour Name 	p_sops->configure_spectral =
2569*5113495bSYour Name 		target_if_spectral_sops_sim_configure_params;
2570*5113495bSYour Name 	p_sops->get_spectral_config = target_if_spectral_sops_sim_get_params;
2571*5113495bSYour Name }
2572*5113495bSYour Name 
2573*5113495bSYour Name #else
2574*5113495bSYour Name /**
2575*5113495bSYour Name  * target_if_init_spectral_simulation_ops() - Initialize spectral target_if
2576*5113495bSYour Name  * internal operations
2577*5113495bSYour Name  * @p_sops: spectral low level ops table
2578*5113495bSYour Name  *
2579*5113495bSYour Name  * Return: None
2580*5113495bSYour Name  */
2581*5113495bSYour Name static void
target_if_init_spectral_simulation_ops(struct target_if_spectral_ops * p_sops)2582*5113495bSYour Name target_if_init_spectral_simulation_ops(struct target_if_spectral_ops *p_sops)
2583*5113495bSYour Name {
2584*5113495bSYour Name 	p_sops->is_spectral_enabled = target_if_sops_is_spectral_enabled;
2585*5113495bSYour Name 	p_sops->is_spectral_active = target_if_sops_is_spectral_active;
2586*5113495bSYour Name 	p_sops->start_spectral_scan = target_if_sops_start_spectral_scan;
2587*5113495bSYour Name 	p_sops->stop_spectral_scan = target_if_sops_stop_spectral_scan;
2588*5113495bSYour Name 	p_sops->configure_spectral = target_if_spectral_sops_configure_params;
2589*5113495bSYour Name 	p_sops->get_spectral_config = target_if_spectral_sops_get_params;
2590*5113495bSYour Name }
2591*5113495bSYour Name #endif
2592*5113495bSYour Name 
2593*5113495bSYour Name /**
2594*5113495bSYour Name  * target_if_init_spectral_ops_common() - Initialize Spectral target_if internal
2595*5113495bSYour Name  * operations common to all Spectral chipset generations
2596*5113495bSYour Name  *
2597*5113495bSYour Name  * Initializes target_if_spectral_ops common to all chipset generations
2598*5113495bSYour Name  *
2599*5113495bSYour Name  * Return: None
2600*5113495bSYour Name  */
2601*5113495bSYour Name static void
target_if_init_spectral_ops_common(void)2602*5113495bSYour Name target_if_init_spectral_ops_common(void)
2603*5113495bSYour Name {
2604*5113495bSYour Name 	struct target_if_spectral_ops *p_sops = &spectral_ops;
2605*5113495bSYour Name 
2606*5113495bSYour Name 	p_sops->get_tsf64 = target_if_spectral_get_tsf64;
2607*5113495bSYour Name 	p_sops->get_capability = target_if_spectral_get_capability;
2608*5113495bSYour Name 	p_sops->set_rxfilter = target_if_spectral_set_rxfilter;
2609*5113495bSYour Name 	p_sops->get_rxfilter = target_if_spectral_get_rxfilter;
2610*5113495bSYour Name 
2611*5113495bSYour Name 	target_if_init_spectral_simulation_ops(p_sops);
2612*5113495bSYour Name 
2613*5113495bSYour Name 	p_sops->get_extension_channel =
2614*5113495bSYour Name 	    target_if_spectral_get_extension_channel;
2615*5113495bSYour Name 	p_sops->get_ctl_noisefloor = target_if_spectral_get_ctl_noisefloor;
2616*5113495bSYour Name 	p_sops->get_ext_noisefloor = target_if_spectral_get_ext_noisefloor;
2617*5113495bSYour Name 	p_sops->get_ent_spectral_mask = target_if_spectral_get_ent_mask;
2618*5113495bSYour Name 	p_sops->get_mac_address = target_if_spectral_get_macaddr;
2619*5113495bSYour Name 	p_sops->get_current_channel = target_if_spectral_get_current_channel;
2620*5113495bSYour Name 	p_sops->reset_hw = target_if_spectral_reset_hw;
2621*5113495bSYour Name 	p_sops->get_chain_noise_floor =
2622*5113495bSYour Name 	    target_if_spectral_get_chain_noise_floor;
2623*5113495bSYour Name }
2624*5113495bSYour Name 
2625*5113495bSYour Name /**
2626*5113495bSYour Name  * target_if_init_spectral_ops_gen2() - Initialize Spectral target_if internal
2627*5113495bSYour Name  * operations specific to Spectral chipset generation 2.
2628*5113495bSYour Name  *
2629*5113495bSYour Name  * Initializes target_if_spectral_ops specific to Spectral chipset generation 2.
2630*5113495bSYour Name  *
2631*5113495bSYour Name  * Return: None
2632*5113495bSYour Name  */
2633*5113495bSYour Name static void
target_if_init_spectral_ops_gen2(void)2634*5113495bSYour Name target_if_init_spectral_ops_gen2(void)
2635*5113495bSYour Name {
2636*5113495bSYour Name 	struct target_if_spectral_ops *p_sops = &spectral_ops;
2637*5113495bSYour Name 
2638*5113495bSYour Name 	p_sops->spectral_process_phyerr = target_if_process_phyerr_gen2;
2639*5113495bSYour Name }
2640*5113495bSYour Name 
2641*5113495bSYour Name #ifdef BIG_ENDIAN_HOST
2642*5113495bSYour Name /**
2643*5113495bSYour Name  * spectral_is_host_byte_swap_required() - Check if byte swap has to be done
2644*5113495bSYour Name  * on the Host
2645*5113495bSYour Name  * @pdev: pdev pointer
2646*5113495bSYour Name  * @is_swap_required: Pointer to caller variable
2647*5113495bSYour Name  *
2648*5113495bSYour Name  * Return: QDF_STATUS of operation
2649*5113495bSYour Name  */
2650*5113495bSYour Name static QDF_STATUS
spectral_is_host_byte_swap_required(struct wlan_objmgr_pdev * pdev,bool * is_swap_required)2651*5113495bSYour Name spectral_is_host_byte_swap_required(struct wlan_objmgr_pdev *pdev,
2652*5113495bSYour Name 				    bool *is_swap_required)
2653*5113495bSYour Name {
2654*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
2655*5113495bSYour Name 	struct wmi_unified *wmi_handle;
2656*5113495bSYour Name 
2657*5113495bSYour Name 	if (!pdev) {
2658*5113495bSYour Name 		spectral_err("pdev is null");
2659*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
2660*5113495bSYour Name 	}
2661*5113495bSYour Name 
2662*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
2663*5113495bSYour Name 	if (!psoc) {
2664*5113495bSYour Name 		spectral_err("psoc is null");
2665*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
2666*5113495bSYour Name 	}
2667*5113495bSYour Name 
2668*5113495bSYour Name 	wmi_handle =  get_wmi_unified_hdl_from_psoc(psoc);
2669*5113495bSYour Name 	if (!wmi_handle) {
2670*5113495bSYour Name 		spectral_err("wmi handle is null");
2671*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
2672*5113495bSYour Name 	}
2673*5113495bSYour Name 
2674*5113495bSYour Name 	/**
2675*5113495bSYour Name 	 * If a chipset supports byte-swap inside the target itself, then no
2676*5113495bSYour Name 	 * need to apply byte swap on the Host.
2677*5113495bSYour Name 	 */
2678*5113495bSYour Name 	*is_swap_required = !target_if_spectral_wmi_service_enabled(
2679*5113495bSYour Name 				psoc, wmi_handle,
2680*5113495bSYour Name 				wmi_service_phy_dma_byte_swap_support);
2681*5113495bSYour Name 
2682*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
2683*5113495bSYour Name }
2684*5113495bSYour Name 
2685*5113495bSYour Name /**
2686*5113495bSYour Name  * target_if_spectral_init_byte_swap_funcs_gen3() - Initialize byte-swap
2687*5113495bSYour Name  * operations for Spectral chipset generation 3.
2688*5113495bSYour Name  * @spectral: Spectral LMAC object
2689*5113495bSYour Name  * @p_sops: Spectral function pointer table
2690*5113495bSYour Name  *
2691*5113495bSYour Name  * Return: None
2692*5113495bSYour Name  */
2693*5113495bSYour Name static void
target_if_spectral_init_byte_swap_funcs_gen3(struct target_if_spectral * spectral,struct target_if_spectral_ops * p_sops)2694*5113495bSYour Name target_if_spectral_init_byte_swap_funcs_gen3(
2695*5113495bSYour Name 	struct target_if_spectral *spectral,
2696*5113495bSYour Name 	struct target_if_spectral_ops *p_sops)
2697*5113495bSYour Name {
2698*5113495bSYour Name 	bool is_swap_required;
2699*5113495bSYour Name 	QDF_STATUS status;
2700*5113495bSYour Name 
2701*5113495bSYour Name 	if (!spectral) {
2702*5113495bSYour Name 		spectral_err("spectral variable is null");
2703*5113495bSYour Name 		return;
2704*5113495bSYour Name 	}
2705*5113495bSYour Name 	if (!p_sops) {
2706*5113495bSYour Name 		spectral_err("spectral ops variable is null");
2707*5113495bSYour Name 		return;
2708*5113495bSYour Name 	}
2709*5113495bSYour Name 	status = spectral_is_host_byte_swap_required(spectral->pdev_obj,
2710*5113495bSYour Name 						     &is_swap_required);
2711*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
2712*5113495bSYour Name 		spectral_err("Failed to check whether byte swap is required");
2713*5113495bSYour Name 		return;
2714*5113495bSYour Name 	}
2715*5113495bSYour Name 
2716*5113495bSYour Name 	if (is_swap_required) {
2717*5113495bSYour Name 		p_sops->byte_swap_headers =
2718*5113495bSYour Name 			target_if_byte_swap_spectral_headers_gen3;
2719*5113495bSYour Name 		p_sops->byte_swap_fft_bins =
2720*5113495bSYour Name 			target_if_byte_swap_spectral_fft_bins_gen3;
2721*5113495bSYour Name 	} else {
2722*5113495bSYour Name 		p_sops->byte_swap_headers = NULL;
2723*5113495bSYour Name 		p_sops->byte_swap_fft_bins = NULL;
2724*5113495bSYour Name 	}
2725*5113495bSYour Name }
2726*5113495bSYour Name #else
2727*5113495bSYour Name static void
target_if_spectral_init_byte_swap_funcs_gen3(struct target_if_spectral * spectral,struct target_if_spectral_ops * p_sops)2728*5113495bSYour Name target_if_spectral_init_byte_swap_funcs_gen3(
2729*5113495bSYour Name 	struct target_if_spectral *spectral,
2730*5113495bSYour Name 	struct target_if_spectral_ops *p_sops)
2731*5113495bSYour Name {
2732*5113495bSYour Name 	if (!p_sops) {
2733*5113495bSYour Name 		spectral_err("spectral ops variable is null");
2734*5113495bSYour Name 		return;
2735*5113495bSYour Name 	}
2736*5113495bSYour Name 
2737*5113495bSYour Name 	/* Byte-swap is not required for little-endian Hosts */
2738*5113495bSYour Name 	p_sops->byte_swap_headers = NULL;
2739*5113495bSYour Name 	p_sops->byte_swap_fft_bins = NULL;
2740*5113495bSYour Name }
2741*5113495bSYour Name #endif /* BIG_ENDIAN_HOST */
2742*5113495bSYour Name 
2743*5113495bSYour Name /**
2744*5113495bSYour Name  * target_if_init_spectral_ops_gen3() - Initialize Spectral target_if internal
2745*5113495bSYour Name  * operations specific to Spectral chipset generation 3.
2746*5113495bSYour Name  * @spectral: Spectral LMAC object
2747*5113495bSYour Name  *
2748*5113495bSYour Name  * Initializes target_if_spectral_ops specific to Spectral chipset generation 3.
2749*5113495bSYour Name  *
2750*5113495bSYour Name  * Return: None
2751*5113495bSYour Name  */
2752*5113495bSYour Name static void
target_if_init_spectral_ops_gen3(struct target_if_spectral * spectral)2753*5113495bSYour Name target_if_init_spectral_ops_gen3(struct target_if_spectral *spectral)
2754*5113495bSYour Name {
2755*5113495bSYour Name 	struct target_if_spectral_ops *p_sops = &spectral_ops;
2756*5113495bSYour Name 
2757*5113495bSYour Name 	p_sops->process_spectral_report =
2758*5113495bSYour Name 			target_if_spectral_process_report_gen3;
2759*5113495bSYour Name 
2760*5113495bSYour Name 	target_if_spectral_init_byte_swap_funcs_gen3(spectral, p_sops);
2761*5113495bSYour Name }
2762*5113495bSYour Name 
2763*5113495bSYour Name /**
2764*5113495bSYour Name  * target_if_init_spectral_ops() - Initialize target_if internal Spectral
2765*5113495bSYour Name  * operations.
2766*5113495bSYour Name  * @spectral: Pointer to Spectral target_if internal private data
2767*5113495bSYour Name  *
2768*5113495bSYour Name  * Initializes all function pointers in target_if_spectral_ops for
2769*5113495bSYour Name  * all generations
2770*5113495bSYour Name  *
2771*5113495bSYour Name  * Return: None
2772*5113495bSYour Name  */
2773*5113495bSYour Name static void
target_if_init_spectral_ops(struct target_if_spectral * spectral)2774*5113495bSYour Name target_if_init_spectral_ops(struct target_if_spectral *spectral)
2775*5113495bSYour Name {
2776*5113495bSYour Name 	target_if_init_spectral_ops_common();
2777*5113495bSYour Name 	if (spectral->spectral_gen == SPECTRAL_GEN2)
2778*5113495bSYour Name 		target_if_init_spectral_ops_gen2();
2779*5113495bSYour Name 	else if (spectral->spectral_gen == SPECTRAL_GEN3)
2780*5113495bSYour Name 		target_if_init_spectral_ops_gen3(spectral);
2781*5113495bSYour Name 	else
2782*5113495bSYour Name 		spectral_err("Invalid Spectral generation");
2783*5113495bSYour Name }
2784*5113495bSYour Name 
2785*5113495bSYour Name /*
2786*5113495bSYour Name  * Dummy Functions:
2787*5113495bSYour Name  * These functions are initially registered to avoid any crashes due to
2788*5113495bSYour Name  * invocation of spectral functions before they are registered.
2789*5113495bSYour Name  */
2790*5113495bSYour Name 
2791*5113495bSYour Name static uint64_t
null_get_tsf64(void * arg)2792*5113495bSYour Name null_get_tsf64(void *arg)
2793*5113495bSYour Name {
2794*5113495bSYour Name 	spectral_ops_not_registered("get_tsf64");
2795*5113495bSYour Name 	return 0;
2796*5113495bSYour Name }
2797*5113495bSYour Name 
2798*5113495bSYour Name static uint32_t
null_get_capability(void * arg,enum spectral_capability_type type)2799*5113495bSYour Name null_get_capability(void *arg, enum spectral_capability_type type)
2800*5113495bSYour Name {
2801*5113495bSYour Name 	/*
2802*5113495bSYour Name 	 * TODO : We should have conditional compilation to get the capability
2803*5113495bSYour Name 	 *      : We have not yet attahced ATH layer here, so there is no
2804*5113495bSYour Name 	 *      : way to check the HAL capbalities
2805*5113495bSYour Name 	 */
2806*5113495bSYour Name 	spectral_ops_not_registered("get_capability");
2807*5113495bSYour Name 
2808*5113495bSYour Name 	/* TODO : For the time being, we are returning TRUE */
2809*5113495bSYour Name 	return true;
2810*5113495bSYour Name }
2811*5113495bSYour Name 
2812*5113495bSYour Name static uint32_t
null_set_rxfilter(void * arg,int rxfilter)2813*5113495bSYour Name null_set_rxfilter(void *arg, int rxfilter)
2814*5113495bSYour Name {
2815*5113495bSYour Name 	spectral_ops_not_registered("set_rxfilter");
2816*5113495bSYour Name 	return 1;
2817*5113495bSYour Name }
2818*5113495bSYour Name 
2819*5113495bSYour Name static uint32_t
null_get_rxfilter(void * arg)2820*5113495bSYour Name null_get_rxfilter(void *arg)
2821*5113495bSYour Name {
2822*5113495bSYour Name 	spectral_ops_not_registered("get_rxfilter");
2823*5113495bSYour Name 	return 0;
2824*5113495bSYour Name }
2825*5113495bSYour Name 
2826*5113495bSYour Name static uint32_t
null_is_spectral_active(void * arg,enum spectral_scan_mode smode)2827*5113495bSYour Name null_is_spectral_active(void *arg, enum spectral_scan_mode smode)
2828*5113495bSYour Name {
2829*5113495bSYour Name 	spectral_ops_not_registered("is_spectral_active");
2830*5113495bSYour Name 	return 1;
2831*5113495bSYour Name }
2832*5113495bSYour Name 
2833*5113495bSYour Name static uint32_t
null_is_spectral_enabled(void * arg,enum spectral_scan_mode smode)2834*5113495bSYour Name null_is_spectral_enabled(void *arg, enum spectral_scan_mode smode)
2835*5113495bSYour Name {
2836*5113495bSYour Name 	spectral_ops_not_registered("is_spectral_enabled");
2837*5113495bSYour Name 	return 1;
2838*5113495bSYour Name }
2839*5113495bSYour Name 
2840*5113495bSYour Name static uint32_t
null_start_spectral_scan(void * arg,enum spectral_scan_mode smode,enum spectral_cp_error_code * err)2841*5113495bSYour Name null_start_spectral_scan(void *arg, enum spectral_scan_mode smode,
2842*5113495bSYour Name 			 enum spectral_cp_error_code *err)
2843*5113495bSYour Name {
2844*5113495bSYour Name 	spectral_ops_not_registered("start_spectral_scan");
2845*5113495bSYour Name 	return 1;
2846*5113495bSYour Name }
2847*5113495bSYour Name 
2848*5113495bSYour Name static uint32_t
null_stop_spectral_scan(void * arg,enum spectral_scan_mode smode)2849*5113495bSYour Name null_stop_spectral_scan(void *arg, enum spectral_scan_mode smode)
2850*5113495bSYour Name {
2851*5113495bSYour Name 	spectral_ops_not_registered("stop_spectral_scan");
2852*5113495bSYour Name 	return 1;
2853*5113495bSYour Name }
2854*5113495bSYour Name 
2855*5113495bSYour Name static uint32_t
null_get_extension_channel(void * arg,enum spectral_scan_mode smode)2856*5113495bSYour Name null_get_extension_channel(void *arg, enum spectral_scan_mode smode)
2857*5113495bSYour Name {
2858*5113495bSYour Name 	spectral_ops_not_registered("get_extension_channel");
2859*5113495bSYour Name 	return 1;
2860*5113495bSYour Name }
2861*5113495bSYour Name 
2862*5113495bSYour Name static int8_t
null_get_ctl_noisefloor(void * arg)2863*5113495bSYour Name null_get_ctl_noisefloor(void *arg)
2864*5113495bSYour Name {
2865*5113495bSYour Name 	spectral_ops_not_registered("get_ctl_noisefloor");
2866*5113495bSYour Name 	return 1;
2867*5113495bSYour Name }
2868*5113495bSYour Name 
2869*5113495bSYour Name static int8_t
null_get_ext_noisefloor(void * arg)2870*5113495bSYour Name null_get_ext_noisefloor(void *arg)
2871*5113495bSYour Name {
2872*5113495bSYour Name 	spectral_ops_not_registered("get_ext_noisefloor");
2873*5113495bSYour Name 	return 0;
2874*5113495bSYour Name }
2875*5113495bSYour Name 
2876*5113495bSYour Name static uint32_t
null_configure_spectral(void * arg,struct spectral_config * params,enum spectral_scan_mode smode)2877*5113495bSYour Name null_configure_spectral(void *arg, struct spectral_config *params,
2878*5113495bSYour Name 			enum spectral_scan_mode smode)
2879*5113495bSYour Name {
2880*5113495bSYour Name 	spectral_ops_not_registered("configure_spectral");
2881*5113495bSYour Name 	return 0;
2882*5113495bSYour Name }
2883*5113495bSYour Name 
2884*5113495bSYour Name static uint32_t
null_get_spectral_config(void * arg,struct spectral_config * params,enum spectral_scan_mode smode)2885*5113495bSYour Name null_get_spectral_config(void *arg, struct spectral_config *params,
2886*5113495bSYour Name 			 enum spectral_scan_mode smode)
2887*5113495bSYour Name {
2888*5113495bSYour Name 	spectral_ops_not_registered("get_spectral_config");
2889*5113495bSYour Name 	return 0;
2890*5113495bSYour Name }
2891*5113495bSYour Name 
2892*5113495bSYour Name static uint32_t
null_get_ent_spectral_mask(void * arg)2893*5113495bSYour Name null_get_ent_spectral_mask(void *arg)
2894*5113495bSYour Name {
2895*5113495bSYour Name 	spectral_ops_not_registered("get_ent_spectral_mask");
2896*5113495bSYour Name 	return 0;
2897*5113495bSYour Name }
2898*5113495bSYour Name 
2899*5113495bSYour Name static uint32_t
null_get_mac_address(void * arg,char * addr)2900*5113495bSYour Name null_get_mac_address(void *arg, char *addr)
2901*5113495bSYour Name {
2902*5113495bSYour Name 	spectral_ops_not_registered("get_mac_address");
2903*5113495bSYour Name 	return 0;
2904*5113495bSYour Name }
2905*5113495bSYour Name 
2906*5113495bSYour Name static uint32_t
null_get_current_channel(void * arg,enum spectral_scan_mode smode)2907*5113495bSYour Name null_get_current_channel(void *arg, enum spectral_scan_mode smode)
2908*5113495bSYour Name {
2909*5113495bSYour Name 	spectral_ops_not_registered("get_current_channel");
2910*5113495bSYour Name 	return 0;
2911*5113495bSYour Name }
2912*5113495bSYour Name 
2913*5113495bSYour Name static uint32_t
null_reset_hw(void * arg)2914*5113495bSYour Name null_reset_hw(void *arg)
2915*5113495bSYour Name {
2916*5113495bSYour Name 	spectral_ops_not_registered("get_current_channel");
2917*5113495bSYour Name 	return 0;
2918*5113495bSYour Name }
2919*5113495bSYour Name 
2920*5113495bSYour Name static uint32_t
null_get_chain_noise_floor(void * arg,int16_t * nf_buf)2921*5113495bSYour Name null_get_chain_noise_floor(void *arg, int16_t *nf_buf)
2922*5113495bSYour Name {
2923*5113495bSYour Name 	spectral_ops_not_registered("get_chain_noise_floor");
2924*5113495bSYour Name 	return 0;
2925*5113495bSYour Name }
2926*5113495bSYour Name 
2927*5113495bSYour Name static int
null_spectral_process_phyerr(struct target_if_spectral * spectral,uint8_t * data,uint32_t datalen,struct target_if_spectral_rfqual_info * p_rfqual,struct target_if_spectral_chan_info * p_chaninfo,uint64_t tsf64,struct target_if_spectral_acs_stats * acs_stats)2928*5113495bSYour Name null_spectral_process_phyerr(struct target_if_spectral *spectral,
2929*5113495bSYour Name 			     uint8_t *data,
2930*5113495bSYour Name 			     uint32_t datalen,
2931*5113495bSYour Name 			     struct target_if_spectral_rfqual_info *p_rfqual,
2932*5113495bSYour Name 			     struct target_if_spectral_chan_info *p_chaninfo,
2933*5113495bSYour Name 			     uint64_t tsf64,
2934*5113495bSYour Name 			     struct target_if_spectral_acs_stats *acs_stats)
2935*5113495bSYour Name {
2936*5113495bSYour Name 	spectral_ops_not_registered("spectral_process_phyerr");
2937*5113495bSYour Name 	return 0;
2938*5113495bSYour Name }
2939*5113495bSYour Name 
2940*5113495bSYour Name static int
null_process_spectral_report(struct wlan_objmgr_pdev * pdev,void * payload)2941*5113495bSYour Name null_process_spectral_report(struct wlan_objmgr_pdev *pdev,
2942*5113495bSYour Name 			     void *payload)
2943*5113495bSYour Name {
2944*5113495bSYour Name 	spectral_ops_not_registered("process_spectral_report");
2945*5113495bSYour Name 	return 0;
2946*5113495bSYour Name }
2947*5113495bSYour Name /**
2948*5113495bSYour Name  * target_if_spectral_init_dummy_function_table() -
2949*5113495bSYour Name  * Initialize target_if internal
2950*5113495bSYour Name  * Spectral operations to dummy functions
2951*5113495bSYour Name  * @ps: Pointer to Spectral target_if internal private data
2952*5113495bSYour Name  *
2953*5113495bSYour Name  * Initialize all the function pointers in target_if_spectral_ops with
2954*5113495bSYour Name  * dummy functions.
2955*5113495bSYour Name  *
2956*5113495bSYour Name  * Return: None
2957*5113495bSYour Name  */
2958*5113495bSYour Name static void
target_if_spectral_init_dummy_function_table(struct target_if_spectral * ps)2959*5113495bSYour Name target_if_spectral_init_dummy_function_table(struct target_if_spectral *ps)
2960*5113495bSYour Name {
2961*5113495bSYour Name 	struct target_if_spectral_ops *p_sops = GET_TARGET_IF_SPECTRAL_OPS(ps);
2962*5113495bSYour Name 
2963*5113495bSYour Name 	p_sops->get_tsf64 = null_get_tsf64;
2964*5113495bSYour Name 	p_sops->get_capability = null_get_capability;
2965*5113495bSYour Name 	p_sops->set_rxfilter = null_set_rxfilter;
2966*5113495bSYour Name 	p_sops->get_rxfilter = null_get_rxfilter;
2967*5113495bSYour Name 	p_sops->is_spectral_enabled = null_is_spectral_enabled;
2968*5113495bSYour Name 	p_sops->is_spectral_active = null_is_spectral_active;
2969*5113495bSYour Name 	p_sops->start_spectral_scan = null_start_spectral_scan;
2970*5113495bSYour Name 	p_sops->stop_spectral_scan = null_stop_spectral_scan;
2971*5113495bSYour Name 	p_sops->get_extension_channel = null_get_extension_channel;
2972*5113495bSYour Name 	p_sops->get_ctl_noisefloor = null_get_ctl_noisefloor;
2973*5113495bSYour Name 	p_sops->get_ext_noisefloor = null_get_ext_noisefloor;
2974*5113495bSYour Name 	p_sops->configure_spectral = null_configure_spectral;
2975*5113495bSYour Name 	p_sops->get_spectral_config = null_get_spectral_config;
2976*5113495bSYour Name 	p_sops->get_ent_spectral_mask = null_get_ent_spectral_mask;
2977*5113495bSYour Name 	p_sops->get_mac_address = null_get_mac_address;
2978*5113495bSYour Name 	p_sops->get_current_channel = null_get_current_channel;
2979*5113495bSYour Name 	p_sops->reset_hw = null_reset_hw;
2980*5113495bSYour Name 	p_sops->get_chain_noise_floor = null_get_chain_noise_floor;
2981*5113495bSYour Name 	p_sops->spectral_process_phyerr = null_spectral_process_phyerr;
2982*5113495bSYour Name 	p_sops->process_spectral_report = null_process_spectral_report;
2983*5113495bSYour Name }
2984*5113495bSYour Name 
2985*5113495bSYour Name /**
2986*5113495bSYour Name  * target_if_spectral_register_funcs() - Initialize target_if internal Spectral
2987*5113495bSYour Name  * operations
2988*5113495bSYour Name  * @spectral: Pointer to Spectral target_if internal private data
2989*5113495bSYour Name  * @p: Pointer to Spectral function table
2990*5113495bSYour Name  *
2991*5113495bSYour Name  * Return: None
2992*5113495bSYour Name  */
2993*5113495bSYour Name static void
target_if_spectral_register_funcs(struct target_if_spectral * spectral,struct target_if_spectral_ops * p)2994*5113495bSYour Name target_if_spectral_register_funcs(struct target_if_spectral *spectral,
2995*5113495bSYour Name 				  struct target_if_spectral_ops *p)
2996*5113495bSYour Name {
2997*5113495bSYour Name 	struct target_if_spectral_ops *p_sops =
2998*5113495bSYour Name 		GET_TARGET_IF_SPECTRAL_OPS(spectral);
2999*5113495bSYour Name 
3000*5113495bSYour Name 	*p_sops = *p;
3001*5113495bSYour Name }
3002*5113495bSYour Name 
3003*5113495bSYour Name /**
3004*5113495bSYour Name  * target_if_spectral_clear_stats() - Clear Spectral stats
3005*5113495bSYour Name  * @spectral: Pointer to Spectral target_if internal private data
3006*5113495bSYour Name  *
3007*5113495bSYour Name  * Function to clear spectral stats
3008*5113495bSYour Name  *
3009*5113495bSYour Name  * Return: None
3010*5113495bSYour Name  */
3011*5113495bSYour Name static void
target_if_spectral_clear_stats(struct target_if_spectral * spectral)3012*5113495bSYour Name target_if_spectral_clear_stats(struct target_if_spectral *spectral)
3013*5113495bSYour Name {
3014*5113495bSYour Name 	struct target_if_spectral_ops *p_sops =
3015*5113495bSYour Name 		GET_TARGET_IF_SPECTRAL_OPS(spectral);
3016*5113495bSYour Name 
3017*5113495bSYour Name 	qdf_mem_zero(&spectral->spectral_stats,
3018*5113495bSYour Name 		     sizeof(struct target_if_spectral_stats));
3019*5113495bSYour Name 	spectral->spectral_stats.last_reset_tstamp =
3020*5113495bSYour Name 	    p_sops->get_tsf64(spectral);
3021*5113495bSYour Name }
3022*5113495bSYour Name 
3023*5113495bSYour Name /**
3024*5113495bSYour Name  * target_if_spectral_check_hw_capability() - Check whether HW supports spectral
3025*5113495bSYour Name  * @spectral: Pointer to Spectral target_if internal private data
3026*5113495bSYour Name  *
3027*5113495bSYour Name  * Function to check whether hardware supports spectral
3028*5113495bSYour Name  *
3029*5113495bSYour Name  * Return: True if HW supports Spectral, false if HW does not support Spectral
3030*5113495bSYour Name  */
3031*5113495bSYour Name static int
target_if_spectral_check_hw_capability(struct target_if_spectral * spectral)3032*5113495bSYour Name target_if_spectral_check_hw_capability(struct target_if_spectral *spectral)
3033*5113495bSYour Name {
3034*5113495bSYour Name 	struct target_if_spectral_ops *p_sops = NULL;
3035*5113495bSYour Name 	struct spectral_caps *pcap = NULL;
3036*5113495bSYour Name 	int is_spectral_supported = true;
3037*5113495bSYour Name 
3038*5113495bSYour Name 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
3039*5113495bSYour Name 	pcap = &spectral->capability;
3040*5113495bSYour Name 
3041*5113495bSYour Name 	if (p_sops->get_capability(spectral, SPECTRAL_CAP_PHYDIAG) == false) {
3042*5113495bSYour Name 		is_spectral_supported = false;
3043*5113495bSYour Name 		spectral_info("SPECTRAL : No PHYDIAG support");
3044*5113495bSYour Name 		return is_spectral_supported;
3045*5113495bSYour Name 	}
3046*5113495bSYour Name 	pcap->phydiag_cap = 1;
3047*5113495bSYour Name 
3048*5113495bSYour Name 	if (p_sops->get_capability(spectral, SPECTRAL_CAP_RADAR) == false) {
3049*5113495bSYour Name 		is_spectral_supported = false;
3050*5113495bSYour Name 		spectral_info("SPECTRAL : No RADAR support");
3051*5113495bSYour Name 		return is_spectral_supported;
3052*5113495bSYour Name 	}
3053*5113495bSYour Name 	pcap->radar_cap = 1;
3054*5113495bSYour Name 
3055*5113495bSYour Name 	if (p_sops->get_capability(spectral,
3056*5113495bSYour Name 				   SPECTRAL_CAP_SPECTRAL_SCAN) == false) {
3057*5113495bSYour Name 		is_spectral_supported = false;
3058*5113495bSYour Name 		spectral_info("SPECTRAL : No SPECTRAL SUPPORT");
3059*5113495bSYour Name 		return is_spectral_supported;
3060*5113495bSYour Name 	}
3061*5113495bSYour Name 	pcap->spectral_cap = 1;
3062*5113495bSYour Name 
3063*5113495bSYour Name 	if (p_sops->get_capability(spectral, SPECTRAL_CAP_ADVNCD_SPECTRAL_SCAN)
3064*5113495bSYour Name 	    == false) {
3065*5113495bSYour Name 		spectral_info("SPECTRAL : No ADVANCED SPECTRAL SUPPORT");
3066*5113495bSYour Name 	} else {
3067*5113495bSYour Name 		pcap->advncd_spectral_cap = 1;
3068*5113495bSYour Name 	}
3069*5113495bSYour Name 
3070*5113495bSYour Name 	return is_spectral_supported;
3071*5113495bSYour Name }
3072*5113495bSYour Name 
3073*5113495bSYour Name #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION
3074*5113495bSYour Name /**
3075*5113495bSYour Name  * target_if_spectral_detach_simulation() - De-initialize Spectral
3076*5113495bSYour Name  * Simulation functionality
3077*5113495bSYour Name  * @spectral: Pointer to Spectral target_if internal private data
3078*5113495bSYour Name  *
3079*5113495bSYour Name  * Function to de-initialize Spectral Simulation functionality
3080*5113495bSYour Name  *
3081*5113495bSYour Name  * Return: None
3082*5113495bSYour Name  */
3083*5113495bSYour Name static void
target_if_spectral_detach_simulation(struct target_if_spectral * spectral)3084*5113495bSYour Name target_if_spectral_detach_simulation(struct target_if_spectral *spectral)
3085*5113495bSYour Name {
3086*5113495bSYour Name 	target_if_spectral_sim_detach(spectral);
3087*5113495bSYour Name }
3088*5113495bSYour Name 
3089*5113495bSYour Name #else
3090*5113495bSYour Name static void
target_if_spectral_detach_simulation(struct target_if_spectral * spectral)3091*5113495bSYour Name target_if_spectral_detach_simulation(struct target_if_spectral *spectral)
3092*5113495bSYour Name {
3093*5113495bSYour Name }
3094*5113495bSYour Name #endif
3095*5113495bSYour Name 
3096*5113495bSYour Name /**
3097*5113495bSYour Name  * target_if_spectral_detach() - De-initialize target_if Spectral
3098*5113495bSYour Name  * @spectral: Pointer to Spectral target_if internal private data
3099*5113495bSYour Name  *
3100*5113495bSYour Name  * Function to detach target_if spectral
3101*5113495bSYour Name  *
3102*5113495bSYour Name  * Return: None
3103*5113495bSYour Name  */
3104*5113495bSYour Name static void
target_if_spectral_detach(struct target_if_spectral * spectral)3105*5113495bSYour Name target_if_spectral_detach(struct target_if_spectral *spectral)
3106*5113495bSYour Name {
3107*5113495bSYour Name 	enum spectral_scan_mode smode = SPECTRAL_SCAN_MODE_NORMAL;
3108*5113495bSYour Name 	spectral_info("spectral detach");
3109*5113495bSYour Name 
3110*5113495bSYour Name 	if (spectral) {
3111*5113495bSYour Name 		for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++)
3112*5113495bSYour Name 			qdf_spinlock_destroy
3113*5113495bSYour Name 				(&spectral->param_info[smode].osps_lock);
3114*5113495bSYour Name 
3115*5113495bSYour Name 		target_if_spectral_detach_simulation(spectral);
3116*5113495bSYour Name 
3117*5113495bSYour Name 		qdf_spinlock_destroy(&spectral->spectral_lock);
3118*5113495bSYour Name 		qdf_spinlock_destroy(&spectral->noise_pwr_reports_lock);
3119*5113495bSYour Name 
3120*5113495bSYour Name 		qdf_spinlock_destroy(&spectral->detector_list_lock);
3121*5113495bSYour Name 		qdf_spinlock_destroy(&spectral->session_report_info_lock);
3122*5113495bSYour Name 		qdf_spinlock_destroy(&spectral->session_det_map_lock);
3123*5113495bSYour Name 
3124*5113495bSYour Name 		qdf_mem_free(spectral);
3125*5113495bSYour Name 		spectral = NULL;
3126*5113495bSYour Name 	}
3127*5113495bSYour Name }
3128*5113495bSYour Name 
3129*5113495bSYour Name #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION
3130*5113495bSYour Name /**
3131*5113495bSYour Name  * target_if_spectral_attach_simulation() - Initialize Spectral Simulation
3132*5113495bSYour Name  * functionality
3133*5113495bSYour Name  * @spectral: Pointer to Spectral target_if internal private data
3134*5113495bSYour Name  *
3135*5113495bSYour Name  * Function to initialize spectral simulation functionality
3136*5113495bSYour Name  *
3137*5113495bSYour Name  * Return: 0 on success, negative error code on failure
3138*5113495bSYour Name  */
3139*5113495bSYour Name static int
target_if_spectral_attach_simulation(struct target_if_spectral * spectral)3140*5113495bSYour Name target_if_spectral_attach_simulation(struct target_if_spectral *spectral)
3141*5113495bSYour Name {
3142*5113495bSYour Name 	if (target_if_spectral_sim_attach(spectral)) {
3143*5113495bSYour Name 		qdf_mem_free(spectral);
3144*5113495bSYour Name 		return -EPERM;
3145*5113495bSYour Name 	}
3146*5113495bSYour Name 	return 0;
3147*5113495bSYour Name }
3148*5113495bSYour Name 
3149*5113495bSYour Name #else
3150*5113495bSYour Name static int
target_if_spectral_attach_simulation(struct target_if_spectral * spectral)3151*5113495bSYour Name target_if_spectral_attach_simulation(struct target_if_spectral *spectral)
3152*5113495bSYour Name {
3153*5113495bSYour Name 	return 0;
3154*5113495bSYour Name }
3155*5113495bSYour Name #endif
3156*5113495bSYour Name 
3157*5113495bSYour Name /**
3158*5113495bSYour Name  * target_if_spectral_len_adj_swar_init() - Initialize FFT bin length adjustment
3159*5113495bSYour Name  * related info
3160*5113495bSYour Name  * @swar: Pointer to Spectral FFT bin length adjustment SWAR params
3161*5113495bSYour Name  * @rparams: Pointer to Spectral report parameter object
3162*5113495bSYour Name  * @target_type: Target type
3163*5113495bSYour Name  *
3164*5113495bSYour Name  * Function to Initialize parameters related to Spectral FFT bin
3165*5113495bSYour Name  * length adjustment SWARs.
3166*5113495bSYour Name  *
3167*5113495bSYour Name  * Return: void
3168*5113495bSYour Name  */
3169*5113495bSYour Name static void
target_if_spectral_len_adj_swar_init(struct spectral_fft_bin_len_adj_swar * swar,struct spectral_report_params * rparams,uint32_t target_type)3170*5113495bSYour Name target_if_spectral_len_adj_swar_init(struct spectral_fft_bin_len_adj_swar *swar,
3171*5113495bSYour Name 				     struct spectral_report_params *rparams,
3172*5113495bSYour Name 				     uint32_t target_type)
3173*5113495bSYour Name {
3174*5113495bSYour Name 	if (target_type == TARGET_TYPE_QCA8074V2 ||
3175*5113495bSYour Name 	    target_type == TARGET_TYPE_QCA9574 ||
3176*5113495bSYour Name 	    target_type == TARGET_TYPE_QCN9000 ||
3177*5113495bSYour Name 	    target_type == TARGET_TYPE_QCN6122 ||
3178*5113495bSYour Name 	    target_type == TARGET_TYPE_QCN9160 ||
3179*5113495bSYour Name 	    target_type == TARGET_TYPE_QCA5018 ||
3180*5113495bSYour Name 	    target_type == TARGET_TYPE_QCA6750 ||
3181*5113495bSYour Name 	    target_type == TARGET_TYPE_QCA6490 ||
3182*5113495bSYour Name 	    target_type == TARGET_TYPE_KIWI ||
3183*5113495bSYour Name 	    target_type == TARGET_TYPE_MANGO ||
3184*5113495bSYour Name 	    target_type == TARGET_TYPE_PEACH) {
3185*5113495bSYour Name 		swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE;
3186*5113495bSYour Name 		rparams->hw_fft_bin_width = 2;
3187*5113495bSYour Name 	} else if (target_type == TARGET_TYPE_QCA8074 ||
3188*5113495bSYour Name 		 target_type == TARGET_TYPE_QCA6018 ||
3189*5113495bSYour Name 		 target_type == TARGET_TYPE_QCA6390) {
3190*5113495bSYour Name 		swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE;
3191*5113495bSYour Name 		rparams->hw_fft_bin_width = 4;
3192*5113495bSYour Name 	} else {
3193*5113495bSYour Name 		swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_NO_WAR;
3194*5113495bSYour Name 		rparams->hw_fft_bin_width = 1;
3195*5113495bSYour Name 	}
3196*5113495bSYour Name 
3197*5113495bSYour Name 	if (target_type == TARGET_TYPE_QCA8074 ||
3198*5113495bSYour Name 	    target_type == TARGET_TYPE_QCA8074V2 ||
3199*5113495bSYour Name 	    target_type == TARGET_TYPE_QCA9574 ||
3200*5113495bSYour Name 	    target_type == TARGET_TYPE_QCA6018 ||
3201*5113495bSYour Name 	    target_type == TARGET_TYPE_QCN6122 ||
3202*5113495bSYour Name 	    target_type == TARGET_TYPE_QCN9160 ||
3203*5113495bSYour Name 	    target_type == TARGET_TYPE_QCN6432 ||
3204*5113495bSYour Name 	    target_type == TARGET_TYPE_QCA5332 ||
3205*5113495bSYour Name 	    target_type == TARGET_TYPE_QCA5018 ||
3206*5113495bSYour Name 	    target_type == TARGET_TYPE_QCN9000 ||
3207*5113495bSYour Name 	    target_type == TARGET_TYPE_QCA6490 ||
3208*5113495bSYour Name 	    target_type == TARGET_TYPE_QCN9224 ||
3209*5113495bSYour Name 	    target_type == TARGET_TYPE_KIWI ||
3210*5113495bSYour Name 	    target_type == TARGET_TYPE_MANGO ||
3211*5113495bSYour Name 	    target_type == TARGET_TYPE_PEACH) {
3212*5113495bSYour Name 		swar->inband_fftbin_size_adj = 1;
3213*5113495bSYour Name 		swar->null_fftbin_adj = 1;
3214*5113495bSYour Name 	} else {
3215*5113495bSYour Name 		swar->inband_fftbin_size_adj = 0;
3216*5113495bSYour Name 		swar->null_fftbin_adj = 0;
3217*5113495bSYour Name 	}
3218*5113495bSYour Name 
3219*5113495bSYour Name 	if (target_type == TARGET_TYPE_QCA8074V2)
3220*5113495bSYour Name 		swar->packmode_fftbin_size_adj = 1;
3221*5113495bSYour Name 	else
3222*5113495bSYour Name 		swar->packmode_fftbin_size_adj = 0;
3223*5113495bSYour Name }
3224*5113495bSYour Name 
3225*5113495bSYour Name /**
3226*5113495bSYour Name  * target_if_spectral_report_params_init() - Initialize parameters which
3227*5113495bSYour Name  * describes the structure of Spectral reports
3228*5113495bSYour Name  *
3229*5113495bSYour Name  * @rparams: Pointer to Spectral report parameter object
3230*5113495bSYour Name  * @target_type: target type
3231*5113495bSYour Name  *
3232*5113495bSYour Name  * Function to Initialize parameters related to the structure of Spectral
3233*5113495bSYour Name  * reports.
3234*5113495bSYour Name  *
3235*5113495bSYour Name  * Return: void
3236*5113495bSYour Name  */
3237*5113495bSYour Name static void
target_if_spectral_report_params_init(struct spectral_report_params * rparams,uint32_t target_type)3238*5113495bSYour Name target_if_spectral_report_params_init(
3239*5113495bSYour Name 			struct spectral_report_params *rparams,
3240*5113495bSYour Name 			uint32_t target_type)
3241*5113495bSYour Name {
3242*5113495bSYour Name 	enum spectral_scan_mode smode;
3243*5113495bSYour Name 
3244*5113495bSYour Name 	/* This entries are currently used by gen3 chipsets only. Hence
3245*5113495bSYour Name 	 * initialization is done for gen3 alone. In future if other generations
3246*5113495bSYour Name 	 * needs to use them they have to add proper initial values.
3247*5113495bSYour Name 	 */
3248*5113495bSYour Name 	if (target_type == TARGET_TYPE_QCN9000 ||
3249*5113495bSYour Name 	    target_type == TARGET_TYPE_QCN6122 ||
3250*5113495bSYour Name 	    target_type == TARGET_TYPE_QCN9160 ||
3251*5113495bSYour Name 	    target_type == TARGET_TYPE_QCN6432 ||
3252*5113495bSYour Name 	    target_type == TARGET_TYPE_QCA5018 ||
3253*5113495bSYour Name 	    target_type == TARGET_TYPE_QCA6750 ||
3254*5113495bSYour Name 	    target_type == TARGET_TYPE_QCA6490 ||
3255*5113495bSYour Name 	    target_type == TARGET_TYPE_QCA5332 ||
3256*5113495bSYour Name 	    target_type == TARGET_TYPE_QCN9224 ||
3257*5113495bSYour Name 	    target_type == TARGET_TYPE_KIWI ||
3258*5113495bSYour Name 	    target_type == TARGET_TYPE_MANGO ||
3259*5113495bSYour Name 	    target_type == TARGET_TYPE_PEACH) {
3260*5113495bSYour Name 		rparams->version = SPECTRAL_REPORT_FORMAT_VERSION_2;
3261*5113495bSYour Name 		rparams->num_spectral_detectors =
3262*5113495bSYour Name 				NUM_SPECTRAL_DETECTORS_GEN3_V2;
3263*5113495bSYour Name 		smode = SPECTRAL_SCAN_MODE_NORMAL;
3264*5113495bSYour Name 		for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++)
3265*5113495bSYour Name 			rparams->fragmentation_160[smode] = false;
3266*5113495bSYour Name 	} else {
3267*5113495bSYour Name 		rparams->version = SPECTRAL_REPORT_FORMAT_VERSION_1;
3268*5113495bSYour Name 		rparams->num_spectral_detectors =
3269*5113495bSYour Name 				NUM_SPECTRAL_DETECTORS_GEN3_V1;
3270*5113495bSYour Name 		smode = SPECTRAL_SCAN_MODE_NORMAL;
3271*5113495bSYour Name 		for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++)
3272*5113495bSYour Name 			rparams->fragmentation_160[smode] = true;
3273*5113495bSYour Name 	}
3274*5113495bSYour Name 
3275*5113495bSYour Name 	switch (rparams->version) {
3276*5113495bSYour Name 	case SPECTRAL_REPORT_FORMAT_VERSION_1:
3277*5113495bSYour Name 		rparams->ssummary_padding_bytes =
3278*5113495bSYour Name 			NUM_PADDING_BYTES_SSCAN_SUMARY_REPORT_GEN3_V1;
3279*5113495bSYour Name 		rparams->fft_report_hdr_len =
3280*5113495bSYour Name 			FFT_REPORT_HEADER_LENGTH_GEN3_V1;
3281*5113495bSYour Name 		break;
3282*5113495bSYour Name 	case SPECTRAL_REPORT_FORMAT_VERSION_2:
3283*5113495bSYour Name 		rparams->ssummary_padding_bytes =
3284*5113495bSYour Name 			NUM_PADDING_BYTES_SSCAN_SUMARY_REPORT_GEN3_V2;
3285*5113495bSYour Name 		rparams->fft_report_hdr_len =
3286*5113495bSYour Name 			FFT_REPORT_HEADER_LENGTH_GEN3_V2;
3287*5113495bSYour Name 		break;
3288*5113495bSYour Name 	}
3289*5113495bSYour Name 
3290*5113495bSYour Name 	rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_0] =
3291*5113495bSYour Name 						SPECTRAL_SCAN_MODE_NORMAL;
3292*5113495bSYour Name 	if (target_type == TARGET_TYPE_QCN9000 ||
3293*5113495bSYour Name 	    target_type == TARGET_TYPE_QCN6122 ||
3294*5113495bSYour Name 	    target_type == TARGET_TYPE_QCN9224 ||
3295*5113495bSYour Name 	    target_type == TARGET_TYPE_QCN6432 ||
3296*5113495bSYour Name 	    target_type == TARGET_TYPE_QCN9160 ||
3297*5113495bSYour Name 	    target_type == TARGET_TYPE_QCA6490 ||
3298*5113495bSYour Name 	    target_type == TARGET_TYPE_KIWI ||
3299*5113495bSYour Name 	    target_type == TARGET_TYPE_MANGO ||
3300*5113495bSYour Name 	    target_type == TARGET_TYPE_PEACH) {
3301*5113495bSYour Name 		rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_1] =
3302*5113495bSYour Name 						SPECTRAL_SCAN_MODE_AGILE;
3303*5113495bSYour Name 		rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_2] =
3304*5113495bSYour Name 						SPECTRAL_SCAN_MODE_INVALID;
3305*5113495bSYour Name 	} else if (target_type == TARGET_TYPE_QCA5332) {
3306*5113495bSYour Name 		rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_1] =
3307*5113495bSYour Name 						SPECTRAL_SCAN_MODE_INVALID;
3308*5113495bSYour Name 		rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_2] =
3309*5113495bSYour Name 						SPECTRAL_SCAN_MODE_INVALID;
3310*5113495bSYour Name 	} else {
3311*5113495bSYour Name 		rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_1] =
3312*5113495bSYour Name 						SPECTRAL_SCAN_MODE_NORMAL;
3313*5113495bSYour Name 		rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_2] =
3314*5113495bSYour Name 						SPECTRAL_SCAN_MODE_AGILE;
3315*5113495bSYour Name 	}
3316*5113495bSYour Name }
3317*5113495bSYour Name 
3318*5113495bSYour Name /**
3319*5113495bSYour Name  * target_if_spectral_timestamp_war_init() - Initialize Spectral timestamp WAR
3320*5113495bSYour Name  * related info
3321*5113495bSYour Name  * @twar: Pointer to Spectral timstamp WAR related info
3322*5113495bSYour Name  *
3323*5113495bSYour Name  * Function to Initialize parameters related to Spectral timestamp WAR
3324*5113495bSYour Name  *
3325*5113495bSYour Name  * Return: void
3326*5113495bSYour Name  */
3327*5113495bSYour Name static void
target_if_spectral_timestamp_war_init(struct spectral_timestamp_war * twar)3328*5113495bSYour Name target_if_spectral_timestamp_war_init(struct spectral_timestamp_war *twar)
3329*5113495bSYour Name {
3330*5113495bSYour Name 	enum spectral_scan_mode smode;
3331*5113495bSYour Name 
3332*5113495bSYour Name 	smode = SPECTRAL_SCAN_MODE_NORMAL;
3333*5113495bSYour Name 	for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) {
3334*5113495bSYour Name 		twar->last_fft_timestamp[smode] = 0;
3335*5113495bSYour Name 		twar->timestamp_war_offset[smode] = 0;
3336*5113495bSYour Name 	}
3337*5113495bSYour Name 	twar->target_reset_count = 0;
3338*5113495bSYour Name }
3339*5113495bSYour Name 
3340*5113495bSYour Name #ifdef OPTIMIZED_SAMP_MESSAGE
3341*5113495bSYour Name /**
3342*5113495bSYour Name  * target_if_spectral_is_hw_mode_sbs() - Check if the given pdev is in SBS mode
3343*5113495bSYour Name  * @pdev: pdev pointer
3344*5113495bSYour Name  * @is_hw_mode_sbs: Pointer to the variable where this function should write
3345*5113495bSYour Name  * whether the given pdev is in SBS mode
3346*5113495bSYour Name  *
3347*5113495bSYour Name  * Return: QDF_STATUS of operation
3348*5113495bSYour Name  */
3349*5113495bSYour Name static QDF_STATUS
target_if_spectral_is_hw_mode_sbs(struct wlan_objmgr_pdev * pdev,bool * is_hw_mode_sbs)3350*5113495bSYour Name target_if_spectral_is_hw_mode_sbs(struct wlan_objmgr_pdev *pdev,
3351*5113495bSYour Name 				  bool *is_hw_mode_sbs)
3352*5113495bSYour Name {
3353*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
3354*5113495bSYour Name 	struct target_psoc_info *tgt_hdl;
3355*5113495bSYour Name 	enum wmi_host_hw_mode_config_type mode;
3356*5113495bSYour Name 
3357*5113495bSYour Name 	if (!is_hw_mode_sbs) {
3358*5113495bSYour Name 		spectral_err("is_hw_mode_sbs pointer is null.");
3359*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
3360*5113495bSYour Name 	}
3361*5113495bSYour Name 
3362*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
3363*5113495bSYour Name 	if (!psoc) {
3364*5113495bSYour Name 		spectral_err("psoc is null");
3365*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
3366*5113495bSYour Name 	}
3367*5113495bSYour Name 
3368*5113495bSYour Name 	tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc);
3369*5113495bSYour Name 	if (!tgt_hdl) {
3370*5113495bSYour Name 		spectral_err("target_psoc_info is null");
3371*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
3372*5113495bSYour Name 	}
3373*5113495bSYour Name 
3374*5113495bSYour Name 	mode = target_psoc_get_preferred_hw_mode(tgt_hdl);
3375*5113495bSYour Name 	switch (mode) {
3376*5113495bSYour Name 	case WMI_HOST_HW_MODE_SBS_PASSIVE:
3377*5113495bSYour Name 	case WMI_HOST_HW_MODE_SBS:
3378*5113495bSYour Name 	case WMI_HOST_HW_MODE_DBS_SBS:
3379*5113495bSYour Name 	case WMI_HOST_HW_MODE_DBS_OR_SBS:
3380*5113495bSYour Name 		*is_hw_mode_sbs = true;
3381*5113495bSYour Name 		break;
3382*5113495bSYour Name 	default:
3383*5113495bSYour Name 		*is_hw_mode_sbs = false;
3384*5113495bSYour Name 		break;
3385*5113495bSYour Name 	}
3386*5113495bSYour Name 
3387*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
3388*5113495bSYour Name }
3389*5113495bSYour Name 
3390*5113495bSYour Name /**
3391*5113495bSYour Name  * target_if_get_pdev_mac_phy_caps() - Get the MAC_PHY capabilities of a pdev
3392*5113495bSYour Name  * @pdev: pdev pointer
3393*5113495bSYour Name  *
3394*5113495bSYour Name  * Return: On success, pointer to  MAC_PHY capabilities of @pdev.
3395*5113495bSYour Name  * On failure, NULL
3396*5113495bSYour Name  */
3397*5113495bSYour Name static struct wlan_psoc_host_mac_phy_caps *
target_if_get_pdev_mac_phy_caps(struct wlan_objmgr_pdev * pdev)3398*5113495bSYour Name target_if_get_pdev_mac_phy_caps(struct wlan_objmgr_pdev *pdev)
3399*5113495bSYour Name {
3400*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
3401*5113495bSYour Name 	struct wlan_psoc_host_mac_phy_caps *mac_phy_cap_arr;
3402*5113495bSYour Name 	struct target_psoc_info *tgt_psoc_info;
3403*5113495bSYour Name 	uint8_t pdev_id;
3404*5113495bSYour Name 
3405*5113495bSYour Name 	if (!pdev) {
3406*5113495bSYour Name 		spectral_err("pdev is NULL");
3407*5113495bSYour Name 		return NULL;
3408*5113495bSYour Name 	}
3409*5113495bSYour Name 
3410*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
3411*5113495bSYour Name 	if (!psoc) {
3412*5113495bSYour Name 		spectral_err("psoc is null");
3413*5113495bSYour Name 		return NULL;
3414*5113495bSYour Name 	}
3415*5113495bSYour Name 
3416*5113495bSYour Name 	tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc);
3417*5113495bSYour Name 	if (!tgt_psoc_info) {
3418*5113495bSYour Name 		spectral_err("target_psoc_info is null");
3419*5113495bSYour Name 		return NULL;
3420*5113495bSYour Name 	}
3421*5113495bSYour Name 
3422*5113495bSYour Name 	mac_phy_cap_arr = target_psoc_get_mac_phy_cap(tgt_psoc_info);
3423*5113495bSYour Name 	if (!mac_phy_cap_arr) {
3424*5113495bSYour Name 		spectral_err("mac phy cap array is null");
3425*5113495bSYour Name 		return NULL;
3426*5113495bSYour Name 	}
3427*5113495bSYour Name 
3428*5113495bSYour Name 	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
3429*5113495bSYour Name 	return &mac_phy_cap_arr[pdev_id];
3430*5113495bSYour Name }
3431*5113495bSYour Name 
3432*5113495bSYour Name /**
3433*5113495bSYour Name  * struct target_if_sscan_pdev_phy_info - PHY information of the pdev on
3434*5113495bSYour Name  * which sscan is done. A pointer to an instance of this structure is passed
3435*5113495bSYour Name  * as an argument to the iterator function target_if_find_sscan_pdev_phya1()
3436*5113495bSYour Name  * @phy_id: PHY ID of this pdev
3437*5113495bSYour Name  * @is_using_phya1: Pointer to the variable where the iterator function should
3438*5113495bSYour Name  * populate whether the given pdev is using PHYA1
3439*5113495bSYour Name  */
3440*5113495bSYour Name struct target_if_sscan_pdev_phy_info {
3441*5113495bSYour Name 	uint8_t phy_id;
3442*5113495bSYour Name 	bool *is_using_phya1;
3443*5113495bSYour Name };
3444*5113495bSYour Name 
3445*5113495bSYour Name /**
3446*5113495bSYour Name  * target_if_find_sscan_pdev_phya1() - This is an iterator function to
3447*5113495bSYour Name  * wlan_objmgr_iterate_obj_list(). It checks whether a given sscan_pdev (pdev on
3448*5113495bSYour Name  * which sscan is currently issued) is using PHYA1 by comparing against the pdev
3449*5113495bSYour Name  * argument given by the wlan_objmgr_iterate_obj_list()
3450*5113495bSYour Name  * @psoc: Pointer to psoc
3451*5113495bSYour Name  * @object: Pointer to pdev
3452*5113495bSYour Name  * @arg: Pointer to target_if_sscan_pdev_phy_info of the sscan_pdev for which
3453*5113495bSYour Name  * we want to check if it uses PHYA1
3454*5113495bSYour Name  *
3455*5113495bSYour Name  * Return: None
3456*5113495bSYour Name  */
3457*5113495bSYour Name static void
target_if_find_sscan_pdev_phya1(struct wlan_objmgr_psoc * psoc,void * object,void * arg)3458*5113495bSYour Name target_if_find_sscan_pdev_phya1(struct wlan_objmgr_psoc *psoc,
3459*5113495bSYour Name 				void *object, void *arg)
3460*5113495bSYour Name {
3461*5113495bSYour Name 	struct target_if_sscan_pdev_phy_info *sscan_pdev_phy_info = arg;
3462*5113495bSYour Name 	struct wlan_objmgr_pdev *cur_pdev = object;
3463*5113495bSYour Name 	struct wlan_psoc_host_mac_phy_caps *cur_mac_phy_caps;
3464*5113495bSYour Name 
3465*5113495bSYour Name 	cur_mac_phy_caps = target_if_get_pdev_mac_phy_caps(cur_pdev);
3466*5113495bSYour Name 	if (!cur_mac_phy_caps) {
3467*5113495bSYour Name 		spectral_err("Failed to get MAC PHY Capabilities of"
3468*5113495bSYour Name 			     "pdev %pK", cur_pdev);
3469*5113495bSYour Name 		return;
3470*5113495bSYour Name 	}
3471*5113495bSYour Name 
3472*5113495bSYour Name 	spectral_debug("supported_bands: %0x phy_id: %d",
3473*5113495bSYour Name 		       cur_mac_phy_caps->supported_bands,
3474*5113495bSYour Name 		       cur_mac_phy_caps->phy_id);
3475*5113495bSYour Name 
3476*5113495bSYour Name 	/* No need to do anything if the current pdev is same as sscan_pdev */
3477*5113495bSYour Name 	if (sscan_pdev_phy_info->phy_id == cur_mac_phy_caps->phy_id)
3478*5113495bSYour Name 		return;
3479*5113495bSYour Name 
3480*5113495bSYour Name 	/**
3481*5113495bSYour Name 	 * Compare the phy_id of both the SBS pdevs to figure out if
3482*5113495bSYour Name 	 * the sscan_pdev using PHYA1
3483*5113495bSYour Name 	 */
3484*5113495bSYour Name 	if (sscan_pdev_phy_info->phy_id > cur_mac_phy_caps->phy_id)
3485*5113495bSYour Name 		*sscan_pdev_phy_info->is_using_phya1 = true;
3486*5113495bSYour Name 	else
3487*5113495bSYour Name 		*sscan_pdev_phy_info->is_using_phya1 = false;
3488*5113495bSYour Name }
3489*5113495bSYour Name 
3490*5113495bSYour Name /**
3491*5113495bSYour Name  * target_if_spectral_detector_list_init() - Initialize Spectral detector list
3492*5113495bSYour Name  * based on target type
3493*5113495bSYour Name  * @spectral: Pointer to Spectral target_if
3494*5113495bSYour Name  *
3495*5113495bSYour Name  * Function to initialize Spectral detector list for possible combinations of
3496*5113495bSYour Name  * Spectral scan mode and channel width, based on target type.
3497*5113495bSYour Name  *
3498*5113495bSYour Name  * Return: Success/Failure
3499*5113495bSYour Name  */
3500*5113495bSYour Name static QDF_STATUS
target_if_spectral_detector_list_init(struct target_if_spectral * spectral)3501*5113495bSYour Name target_if_spectral_detector_list_init(struct target_if_spectral *spectral)
3502*5113495bSYour Name {
3503*5113495bSYour Name 	struct sscan_detector_list *det_list;
3504*5113495bSYour Name 	enum spectral_scan_mode smode;
3505*5113495bSYour Name 	enum phy_ch_width ch_width;
3506*5113495bSYour Name 	QDF_STATUS ret;
3507*5113495bSYour Name 	bool is_hw_mode_sbs = false, is_using_phya1 = false;
3508*5113495bSYour Name 
3509*5113495bSYour Name 	if (!spectral) {
3510*5113495bSYour Name 		spectral_err_rl("Spectral LMAC object is null");
3511*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
3512*5113495bSYour Name 	}
3513*5113495bSYour Name 
3514*5113495bSYour Name 	/**
3515*5113495bSYour Name 	 * Special handling is required for SBS mode where the detector
3516*5113495bSYour Name 	 * list should be the following.
3517*5113495bSYour Name 	 * For the pdev that use PHYA0:
3518*5113495bSYour Name 	 *    detector 0 for normal mode
3519*5113495bSYour Name 	 *    detector 2 for agile mode
3520*5113495bSYour Name 	 * For the pdev that use PHYA1:
3521*5113495bSYour Name 	 *    detector 1 for normal mode
3522*5113495bSYour Name 	 *    detector 2 for agile mode
3523*5113495bSYour Name 	 *
3524*5113495bSYour Name 	 * There is no direct way of knowing which pdevs are using PHYA0 or
3525*5113495bSYour Name 	 * PHYA1. We need to look at the phy_id of a given pdev and compare
3526*5113495bSYour Name 	 * against other pdevs on the same psoc to figure out whether the given
3527*5113495bSYour Name 	 * pdev is operating using PHYA1.
3528*5113495bSYour Name 	 */
3529*5113495bSYour Name 
3530*5113495bSYour Name 	/* First check whether this pdev is in SBS mode */
3531*5113495bSYour Name 	ret = target_if_spectral_is_hw_mode_sbs(spectral->pdev_obj,
3532*5113495bSYour Name 						&is_hw_mode_sbs);
3533*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(ret)) {
3534*5113495bSYour Name 		spectral_err("Failed to check whether hw mode is SBS");
3535*5113495bSYour Name 		return ret;
3536*5113495bSYour Name 	}
3537*5113495bSYour Name 
3538*5113495bSYour Name 	if (is_hw_mode_sbs) {
3539*5113495bSYour Name 		struct wlan_psoc_host_mac_phy_caps *mac_phy_caps;
3540*5113495bSYour Name 		struct target_if_sscan_pdev_phy_info pdev_phy_info;
3541*5113495bSYour Name 
3542*5113495bSYour Name 		mac_phy_caps =
3543*5113495bSYour Name 			target_if_get_pdev_mac_phy_caps(spectral->pdev_obj);
3544*5113495bSYour Name 		if (!mac_phy_caps) {
3545*5113495bSYour Name 			spectral_err("Failed to get MAC PHY Capabilities of"
3546*5113495bSYour Name 				     "pdev %pK", spectral->pdev_obj);
3547*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
3548*5113495bSYour Name 		}
3549*5113495bSYour Name 
3550*5113495bSYour Name 		spectral_debug("bands: %0x phy_id: %d",
3551*5113495bSYour Name 			       mac_phy_caps->supported_bands,
3552*5113495bSYour Name 			       mac_phy_caps->phy_id);
3553*5113495bSYour Name 
3554*5113495bSYour Name 		pdev_phy_info.phy_id = mac_phy_caps->phy_id;
3555*5113495bSYour Name 		pdev_phy_info.is_using_phya1 = &is_using_phya1;
3556*5113495bSYour Name 
3557*5113495bSYour Name 		/* Iterate over all pdevs on this psoc */
3558*5113495bSYour Name 		wlan_objmgr_iterate_obj_list
3559*5113495bSYour Name 			(wlan_pdev_get_psoc(spectral->pdev_obj),
3560*5113495bSYour Name 			 WLAN_PDEV_OP,
3561*5113495bSYour Name 			 target_if_find_sscan_pdev_phya1,
3562*5113495bSYour Name 			 &pdev_phy_info, 0,
3563*5113495bSYour Name 			 WLAN_SPECTRAL_ID);
3564*5113495bSYour Name 	}
3565*5113495bSYour Name 
3566*5113495bSYour Name 	/**
3567*5113495bSYour Name 	 * We assume there are 2 detectors. The Detector ID coming first will
3568*5113495bSYour Name 	 * always be pri80 detector, and second detector for sec80.
3569*5113495bSYour Name 	 */
3570*5113495bSYour Name 	ch_width = CH_WIDTH_20MHZ;
3571*5113495bSYour Name 	for (; ch_width < CH_WIDTH_MAX; ch_width++) {
3572*5113495bSYour Name 		/* Normal spectral scan */
3573*5113495bSYour Name 		smode = SPECTRAL_SCAN_MODE_NORMAL;
3574*5113495bSYour Name 		spectral_debug("is_hw_mode_sbs: %d is_using_phya1:%d",
3575*5113495bSYour Name 			       is_hw_mode_sbs, is_using_phya1);
3576*5113495bSYour Name 
3577*5113495bSYour Name 		qdf_spin_lock_bh(&spectral->detector_list_lock);
3578*5113495bSYour Name 
3579*5113495bSYour Name 		if (!spectral->supported_sscan_bw_list[smode][ch_width])
3580*5113495bSYour Name 			goto agile_handling;
3581*5113495bSYour Name 
3582*5113495bSYour Name 		det_list = &spectral->detector_list[smode][ch_width];
3583*5113495bSYour Name 		det_list->num_detectors = 1;
3584*5113495bSYour Name 
3585*5113495bSYour Name 		if (is_hw_mode_sbs && is_using_phya1)
3586*5113495bSYour Name 			det_list->detectors[0] = SPECTRAL_DETECTOR_ID_1;
3587*5113495bSYour Name 		else
3588*5113495bSYour Name 			det_list->detectors[0] = SPECTRAL_DETECTOR_ID_0;
3589*5113495bSYour Name 
3590*5113495bSYour Name 		if (is_ch_width_160_or_80p80(ch_width) &&
3591*5113495bSYour Name 		    spectral->rparams.fragmentation_160[smode]) {
3592*5113495bSYour Name 			det_list->num_detectors += 1;
3593*5113495bSYour Name 			det_list->detectors[1] = SPECTRAL_DETECTOR_ID_1;
3594*5113495bSYour Name 		}
3595*5113495bSYour Name 
3596*5113495bSYour Name agile_handling:
3597*5113495bSYour Name 		/* Agile spectral scan */
3598*5113495bSYour Name 		smode = SPECTRAL_SCAN_MODE_AGILE;
3599*5113495bSYour Name 		if (!spectral->supported_sscan_bw_list[smode][ch_width]) {
3600*5113495bSYour Name 			qdf_spin_unlock_bh(&spectral->detector_list_lock);
3601*5113495bSYour Name 			continue;
3602*5113495bSYour Name 		}
3603*5113495bSYour Name 
3604*5113495bSYour Name 		det_list = &spectral->detector_list[smode][ch_width];
3605*5113495bSYour Name 		det_list->num_detectors = 1;
3606*5113495bSYour Name 
3607*5113495bSYour Name 		if (spectral->rparams.fragmentation_160[smode])
3608*5113495bSYour Name 			det_list->detectors[0] = SPECTRAL_DETECTOR_ID_2;
3609*5113495bSYour Name 		else
3610*5113495bSYour Name 			det_list->detectors[0] = SPECTRAL_DETECTOR_ID_1;
3611*5113495bSYour Name 
3612*5113495bSYour Name 		qdf_spin_unlock_bh(&spectral->detector_list_lock);
3613*5113495bSYour Name 	}
3614*5113495bSYour Name 
3615*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
3616*5113495bSYour Name }
3617*5113495bSYour Name #else
3618*5113495bSYour Name 
3619*5113495bSYour Name static QDF_STATUS
target_if_spectral_detector_list_init(struct target_if_spectral * spectral)3620*5113495bSYour Name target_if_spectral_detector_list_init(struct target_if_spectral *spectral)
3621*5113495bSYour Name {
3622*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
3623*5113495bSYour Name }
3624*5113495bSYour Name #endif /* OPTIMIZED_SAMP_MESSAGE */
3625*5113495bSYour Name 
3626*5113495bSYour Name /**
3627*5113495bSYour Name  * target_if_pdev_spectral_init() - Initialize target_if Spectral
3628*5113495bSYour Name  * functionality for the given pdev
3629*5113495bSYour Name  * @pdev: Pointer to pdev object
3630*5113495bSYour Name  *
3631*5113495bSYour Name  * Function to initialize pointer to spectral target_if internal private data
3632*5113495bSYour Name  *
3633*5113495bSYour Name  * Return: On success, pointer to Spectral target_if internal private data, on
3634*5113495bSYour Name  * failure, NULL
3635*5113495bSYour Name  */
3636*5113495bSYour Name void *
target_if_pdev_spectral_init(struct wlan_objmgr_pdev * pdev)3637*5113495bSYour Name target_if_pdev_spectral_init(struct wlan_objmgr_pdev *pdev)
3638*5113495bSYour Name {
3639*5113495bSYour Name 	struct target_if_spectral_ops *p_sops = NULL;
3640*5113495bSYour Name 	struct target_if_spectral *spectral = NULL;
3641*5113495bSYour Name 	uint32_t target_type;
3642*5113495bSYour Name 	uint32_t target_revision;
3643*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
3644*5113495bSYour Name 	struct wlan_lmac_if_target_tx_ops *tgt_tx_ops;
3645*5113495bSYour Name 	enum spectral_scan_mode smode = SPECTRAL_SCAN_MODE_NORMAL;
3646*5113495bSYour Name 	QDF_STATUS status;
3647*5113495bSYour Name 	struct wlan_lmac_if_tx_ops *tx_ops;
3648*5113495bSYour Name 
3649*5113495bSYour Name 	if (!pdev) {
3650*5113495bSYour Name 		spectral_err("SPECTRAL: pdev is NULL!");
3651*5113495bSYour Name 		return NULL;
3652*5113495bSYour Name 	}
3653*5113495bSYour Name 	spectral = (struct target_if_spectral *)qdf_mem_malloc(
3654*5113495bSYour Name 			sizeof(struct target_if_spectral));
3655*5113495bSYour Name 	if (!spectral)
3656*5113495bSYour Name 		return spectral;
3657*5113495bSYour Name 
3658*5113495bSYour Name 	qdf_mem_zero(spectral, sizeof(struct target_if_spectral));
3659*5113495bSYour Name 	/* Store pdev in Spectral */
3660*5113495bSYour Name 	spectral->pdev_obj = pdev;
3661*5113495bSYour Name 	spectral->vdev_id[SPECTRAL_SCAN_MODE_NORMAL] = WLAN_INVALID_VDEV_ID;
3662*5113495bSYour Name 	spectral->vdev_id[SPECTRAL_SCAN_MODE_AGILE] = WLAN_INVALID_VDEV_ID;
3663*5113495bSYour Name 
3664*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
3665*5113495bSYour Name 
3666*5113495bSYour Name 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
3667*5113495bSYour Name 	if (!tx_ops) {
3668*5113495bSYour Name 		spectral_err("tx_ops is NULL");
3669*5113495bSYour Name 		qdf_mem_free(spectral);
3670*5113495bSYour Name 		return NULL;
3671*5113495bSYour Name 	}
3672*5113495bSYour Name 
3673*5113495bSYour Name 	tgt_tx_ops = &tx_ops->target_tx_ops;
3674*5113495bSYour Name 
3675*5113495bSYour Name 	if (tgt_tx_ops->tgt_get_tgt_type) {
3676*5113495bSYour Name 		target_type = tgt_tx_ops->tgt_get_tgt_type(psoc);
3677*5113495bSYour Name 	} else {
3678*5113495bSYour Name 		qdf_mem_free(spectral);
3679*5113495bSYour Name 		return NULL;
3680*5113495bSYour Name 	}
3681*5113495bSYour Name 
3682*5113495bSYour Name 	if (tgt_tx_ops->tgt_get_tgt_revision) {
3683*5113495bSYour Name 		target_revision = tgt_tx_ops->tgt_get_tgt_revision(psoc);
3684*5113495bSYour Name 	} else {
3685*5113495bSYour Name 		qdf_mem_free(spectral);
3686*5113495bSYour Name 		return NULL;
3687*5113495bSYour Name 	}
3688*5113495bSYour Name 
3689*5113495bSYour Name 	/* init the function ptr table */
3690*5113495bSYour Name 	target_if_spectral_init_dummy_function_table(spectral);
3691*5113495bSYour Name 
3692*5113495bSYour Name 	/* get spectral function table */
3693*5113495bSYour Name 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
3694*5113495bSYour Name 	/* TODO : Should this be called here of after ath_attach ? */
3695*5113495bSYour Name 	if (p_sops->get_capability(spectral, SPECTRAL_CAP_PHYDIAG))
3696*5113495bSYour Name 		spectral_info("HAL_CAP_PHYDIAG : Capable");
3697*5113495bSYour Name 
3698*5113495bSYour Name 	/* TODO: Need to fix the capability check for RADAR */
3699*5113495bSYour Name 	if (p_sops->get_capability(spectral, SPECTRAL_CAP_RADAR))
3700*5113495bSYour Name 		spectral_info("HAL_CAP_RADAR   : Capable");
3701*5113495bSYour Name 
3702*5113495bSYour Name 	/* TODO : Need to fix the capability check for SPECTRAL */
3703*5113495bSYour Name 	/* TODO : Should this be called here of after ath_attach ? */
3704*5113495bSYour Name 	if (p_sops->get_capability(spectral, SPECTRAL_CAP_SPECTRAL_SCAN))
3705*5113495bSYour Name 		spectral_info("HAL_CAP_SPECTRAL_SCAN : Capable");
3706*5113495bSYour Name 
3707*5113495bSYour Name 	qdf_spinlock_create(&spectral->spectral_lock);
3708*5113495bSYour Name 	qdf_spinlock_create(&spectral->noise_pwr_reports_lock);
3709*5113495bSYour Name 	target_if_spectral_clear_stats(spectral);
3710*5113495bSYour Name 
3711*5113495bSYour Name 	if (target_type == TARGET_TYPE_QCA8074 ||
3712*5113495bSYour Name 	    target_type == TARGET_TYPE_QCA8074V2 ||
3713*5113495bSYour Name 	    target_type == TARGET_TYPE_QCA9574 ||
3714*5113495bSYour Name 	    target_type == TARGET_TYPE_QCA5332 ||
3715*5113495bSYour Name 	    target_type == TARGET_TYPE_QCA6018 ||
3716*5113495bSYour Name 	    target_type == TARGET_TYPE_QCA5018 ||
3717*5113495bSYour Name 	    target_type == TARGET_TYPE_QCA6390 ||
3718*5113495bSYour Name 	    target_type == TARGET_TYPE_QCN6122 ||
3719*5113495bSYour Name 	    target_type == TARGET_TYPE_QCN9160 ||
3720*5113495bSYour Name 	    target_type == TARGET_TYPE_QCN6432 ||
3721*5113495bSYour Name 	    target_type == TARGET_TYPE_QCA6490 ||
3722*5113495bSYour Name 	    target_type == TARGET_TYPE_QCN9000 ||
3723*5113495bSYour Name 	    target_type == TARGET_TYPE_QCA6750 ||
3724*5113495bSYour Name 	    target_type == TARGET_TYPE_QCN9224 ||
3725*5113495bSYour Name 	    target_type == TARGET_TYPE_KIWI ||
3726*5113495bSYour Name 	    target_type == TARGET_TYPE_MANGO ||
3727*5113495bSYour Name 	    target_type == TARGET_TYPE_PEACH)
3728*5113495bSYour Name 		spectral->direct_dma_support = true;
3729*5113495bSYour Name 
3730*5113495bSYour Name 	target_if_spectral_report_params_init(&spectral->rparams,
3731*5113495bSYour Name 					      target_type);
3732*5113495bSYour Name 	target_if_spectral_len_adj_swar_init(&spectral->len_adj_swar,
3733*5113495bSYour Name 					     &spectral->rparams,
3734*5113495bSYour Name 					     target_type);
3735*5113495bSYour Name 
3736*5113495bSYour Name 	if ((target_type == TARGET_TYPE_QCA8074) ||
3737*5113495bSYour Name 	    (target_type == TARGET_TYPE_QCA8074V2) ||
3738*5113495bSYour Name 	    (target_type == TARGET_TYPE_QCA9574) ||
3739*5113495bSYour Name 	    (target_type == TARGET_TYPE_QCA6018) ||
3740*5113495bSYour Name 	    (target_type == TARGET_TYPE_QCA5018) ||
3741*5113495bSYour Name 	    (target_type == TARGET_TYPE_QCA5332) ||
3742*5113495bSYour Name 	    (target_type == TARGET_TYPE_QCN6122) ||
3743*5113495bSYour Name 	    (target_type == TARGET_TYPE_QCN9160) ||
3744*5113495bSYour Name 	    (target_type == TARGET_TYPE_QCN6432) ||
3745*5113495bSYour Name 	    (target_type == TARGET_TYPE_QCN9000) ||
3746*5113495bSYour Name 	    (target_type == TARGET_TYPE_QCA6290) ||
3747*5113495bSYour Name 	    (target_type == TARGET_TYPE_QCA6390) ||
3748*5113495bSYour Name 	    (target_type == TARGET_TYPE_QCA6490) ||
3749*5113495bSYour Name 	    (target_type == TARGET_TYPE_QCN9224) ||
3750*5113495bSYour Name 	    (target_type == TARGET_TYPE_QCA6750) ||
3751*5113495bSYour Name 	    (target_type == TARGET_TYPE_KIWI) ||
3752*5113495bSYour Name 	    (target_type == TARGET_TYPE_MANGO) ||
3753*5113495bSYour Name 	    (target_type == TARGET_TYPE_PEACH)) {
3754*5113495bSYour Name 		spectral->spectral_gen = SPECTRAL_GEN3;
3755*5113495bSYour Name 		spectral->hdr_sig_exp = SPECTRAL_PHYERR_SIGNATURE_GEN3;
3756*5113495bSYour Name 		spectral->tag_sscan_summary_exp =
3757*5113495bSYour Name 		    TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN3;
3758*5113495bSYour Name 		spectral->tag_sscan_fft_exp = TLV_TAG_SEARCH_FFT_REPORT_GEN3;
3759*5113495bSYour Name 		spectral->tlvhdr_size = SPECTRAL_PHYERR_TLVSIZE_GEN3;
3760*5113495bSYour Name 	} else {
3761*5113495bSYour Name 		spectral->spectral_gen = SPECTRAL_GEN2;
3762*5113495bSYour Name 		spectral->hdr_sig_exp = SPECTRAL_PHYERR_SIGNATURE_GEN2;
3763*5113495bSYour Name 		spectral->tag_sscan_summary_exp =
3764*5113495bSYour Name 		    TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN2;
3765*5113495bSYour Name 		spectral->tag_sscan_fft_exp = TLV_TAG_SEARCH_FFT_REPORT_GEN2;
3766*5113495bSYour Name 		spectral->tlvhdr_size = sizeof(struct spectral_phyerr_tlv_gen2);
3767*5113495bSYour Name 	}
3768*5113495bSYour Name 
3769*5113495bSYour Name 	status = target_if_init_spectral_param_min_max(
3770*5113495bSYour Name 					spectral,
3771*5113495bSYour Name 					spectral->spectral_gen, target_type);
3772*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
3773*5113495bSYour Name 		spectral_err("Failed to initialize parameter min max values");
3774*5113495bSYour Name 		goto fail;
3775*5113495bSYour Name 	}
3776*5113495bSYour Name 
3777*5113495bSYour Name 	target_if_init_spectral_param_properties(spectral);
3778*5113495bSYour Name 	/* Init spectral capability */
3779*5113495bSYour Name 	if (target_if_init_spectral_capability(spectral, target_type) !=
3780*5113495bSYour Name 					QDF_STATUS_SUCCESS) {
3781*5113495bSYour Name 		qdf_mem_free(spectral);
3782*5113495bSYour Name 		return NULL;
3783*5113495bSYour Name 	}
3784*5113495bSYour Name 	if (target_if_spectral_attach_simulation(spectral) < 0)
3785*5113495bSYour Name 		return NULL;
3786*5113495bSYour Name 
3787*5113495bSYour Name 	target_if_init_spectral_ops(spectral);
3788*5113495bSYour Name 	target_if_spectral_timestamp_war_init(&spectral->timestamp_war);
3789*5113495bSYour Name 
3790*5113495bSYour Name 	/* Spectral mode specific init */
3791*5113495bSYour Name 	for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) {
3792*5113495bSYour Name 		spectral->params_valid[smode] = false;
3793*5113495bSYour Name 		qdf_spinlock_create(&spectral->param_info[smode].osps_lock);
3794*5113495bSYour Name 		spectral->param_info[smode].osps_cache.osc_is_valid = 0;
3795*5113495bSYour Name 	}
3796*5113495bSYour Name 
3797*5113495bSYour Name 	target_if_spectral_register_funcs(spectral, &spectral_ops);
3798*5113495bSYour Name 
3799*5113495bSYour Name 	if (target_if_spectral_check_hw_capability(spectral) == false) {
3800*5113495bSYour Name 		goto fail;
3801*5113495bSYour Name 	} else {
3802*5113495bSYour Name 		/*
3803*5113495bSYour Name 		 * TODO: Once the driver architecture transitions to chipset
3804*5113495bSYour Name 		 * versioning based checks, reflect this here.
3805*5113495bSYour Name 		 */
3806*5113495bSYour Name 		spectral->is_160_format = false;
3807*5113495bSYour Name 		spectral->is_lb_edge_extrabins_format = false;
3808*5113495bSYour Name 		spectral->is_rb_edge_extrabins_format = false;
3809*5113495bSYour Name 
3810*5113495bSYour Name 		if (target_type == TARGET_TYPE_QCA9984 ||
3811*5113495bSYour Name 		    target_type == TARGET_TYPE_QCA9888) {
3812*5113495bSYour Name 			spectral->is_160_format = true;
3813*5113495bSYour Name 			spectral->is_lb_edge_extrabins_format = true;
3814*5113495bSYour Name 			spectral->is_rb_edge_extrabins_format = true;
3815*5113495bSYour Name 		} else  if ((target_type == TARGET_TYPE_AR900B) &&
3816*5113495bSYour Name 			    (target_revision == AR900B_REV_2)) {
3817*5113495bSYour Name 			spectral->is_rb_edge_extrabins_format = true;
3818*5113495bSYour Name 		}
3819*5113495bSYour Name 
3820*5113495bSYour Name 		if (target_type == TARGET_TYPE_QCA9984 ||
3821*5113495bSYour Name 		    target_type == TARGET_TYPE_QCA9888)
3822*5113495bSYour Name 			spectral->is_sec80_rssi_war_required = true;
3823*5113495bSYour Name 
3824*5113495bSYour Name 		spectral->use_nl_bcast = SPECTRAL_USE_NL_BCAST;
3825*5113495bSYour Name 
3826*5113495bSYour Name 		if (spectral->spectral_gen == SPECTRAL_GEN3)
3827*5113495bSYour Name 			init_160mhz_delivery_state_machine(spectral);
3828*5113495bSYour Name 	}
3829*5113495bSYour Name 
3830*5113495bSYour Name 	qdf_spinlock_create(&spectral->detector_list_lock);
3831*5113495bSYour Name 	qdf_spinlock_create(&spectral->session_report_info_lock);
3832*5113495bSYour Name 	qdf_spinlock_create(&spectral->session_det_map_lock);
3833*5113495bSYour Name 
3834*5113495bSYour Name 	return spectral;
3835*5113495bSYour Name 
3836*5113495bSYour Name fail:
3837*5113495bSYour Name 	target_if_spectral_detach(spectral);
3838*5113495bSYour Name 	return NULL;
3839*5113495bSYour Name }
3840*5113495bSYour Name 
3841*5113495bSYour Name /**
3842*5113495bSYour Name  * target_if_pdev_spectral_deinit() - De-initialize target_if Spectral
3843*5113495bSYour Name  * functionality for the given pdev
3844*5113495bSYour Name  * @pdev: Pointer to pdev object
3845*5113495bSYour Name  *
3846*5113495bSYour Name  * Function to de-initialize pointer to spectral target_if internal private data
3847*5113495bSYour Name  *
3848*5113495bSYour Name  * Return: None
3849*5113495bSYour Name  */
3850*5113495bSYour Name void
target_if_pdev_spectral_deinit(struct wlan_objmgr_pdev * pdev)3851*5113495bSYour Name target_if_pdev_spectral_deinit(struct wlan_objmgr_pdev *pdev)
3852*5113495bSYour Name {
3853*5113495bSYour Name 	struct target_if_spectral *spectral = NULL;
3854*5113495bSYour Name 
3855*5113495bSYour Name 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
3856*5113495bSYour Name 	if (!spectral) {
3857*5113495bSYour Name 		spectral_err("SPECTRAL : Module doesn't exist");
3858*5113495bSYour Name 		return;
3859*5113495bSYour Name 	}
3860*5113495bSYour Name 	target_if_spectral_detach(spectral);
3861*5113495bSYour Name 
3862*5113495bSYour Name 	return;
3863*5113495bSYour Name }
3864*5113495bSYour Name 
3865*5113495bSYour Name /**
3866*5113495bSYour Name  * target_if_psoc_spectral_deinit() - De-initialize target_if Spectral
3867*5113495bSYour Name  * functionality for the given psoc
3868*5113495bSYour Name  * @psoc: Pointer to psoc object
3869*5113495bSYour Name  *
3870*5113495bSYour Name  * Function to de-initialize pointer to psoc spectral target_if internal
3871*5113495bSYour Name  * private data
3872*5113495bSYour Name  *
3873*5113495bSYour Name  * Return: None
3874*5113495bSYour Name  */
3875*5113495bSYour Name static void
target_if_psoc_spectral_deinit(struct wlan_objmgr_psoc * psoc)3876*5113495bSYour Name target_if_psoc_spectral_deinit(struct wlan_objmgr_psoc *psoc)
3877*5113495bSYour Name {
3878*5113495bSYour Name 	struct target_if_psoc_spectral *psoc_spectral;
3879*5113495bSYour Name 
3880*5113495bSYour Name 	if (!psoc) {
3881*5113495bSYour Name 		spectral_err("psoc is null");
3882*5113495bSYour Name 		return;
3883*5113495bSYour Name 	}
3884*5113495bSYour Name 
3885*5113495bSYour Name 	psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
3886*5113495bSYour Name 	if (!psoc_spectral) {
3887*5113495bSYour Name 		spectral_err("Spectral target_if psoc object is null");
3888*5113495bSYour Name 		return;
3889*5113495bSYour Name 	}
3890*5113495bSYour Name 
3891*5113495bSYour Name 	qdf_mem_free(psoc_spectral);
3892*5113495bSYour Name }
3893*5113495bSYour Name 
3894*5113495bSYour Name /**
3895*5113495bSYour Name  * target_if_psoc_spectral_init() - Initialize target_if Spectral
3896*5113495bSYour Name  * functionality for the given psoc
3897*5113495bSYour Name  * @psoc: Pointer to psoc object
3898*5113495bSYour Name  *
3899*5113495bSYour Name  * Function to initialize pointer to psoc spectral target_if internal
3900*5113495bSYour Name  * private data
3901*5113495bSYour Name  *
3902*5113495bSYour Name  * Return: On success, pointer to Spectral psoc target_if internal
3903*5113495bSYour Name  * private data, on failure, NULL
3904*5113495bSYour Name  */
3905*5113495bSYour Name static void *
target_if_psoc_spectral_init(struct wlan_objmgr_psoc * psoc)3906*5113495bSYour Name target_if_psoc_spectral_init(struct wlan_objmgr_psoc *psoc)
3907*5113495bSYour Name {
3908*5113495bSYour Name 	struct target_if_psoc_spectral *psoc_spectral = NULL;
3909*5113495bSYour Name 
3910*5113495bSYour Name 	if (!psoc) {
3911*5113495bSYour Name 		spectral_err("psoc is null");
3912*5113495bSYour Name 		goto fail;
3913*5113495bSYour Name 	}
3914*5113495bSYour Name 
3915*5113495bSYour Name 	psoc_spectral = (struct target_if_psoc_spectral *)qdf_mem_malloc(
3916*5113495bSYour Name 			sizeof(struct target_if_psoc_spectral));
3917*5113495bSYour Name 	if (!psoc_spectral) {
3918*5113495bSYour Name 		spectral_err("Spectral lmac psoc object allocation failed");
3919*5113495bSYour Name 		goto fail;
3920*5113495bSYour Name 	}
3921*5113495bSYour Name 
3922*5113495bSYour Name 	psoc_spectral->psoc_obj = psoc;
3923*5113495bSYour Name 
3924*5113495bSYour Name 	return psoc_spectral;
3925*5113495bSYour Name 
3926*5113495bSYour Name fail:
3927*5113495bSYour Name 	if (psoc_spectral)
3928*5113495bSYour Name 		target_if_psoc_spectral_deinit(psoc);
3929*5113495bSYour Name 
3930*5113495bSYour Name 	return psoc_spectral;
3931*5113495bSYour Name }
3932*5113495bSYour Name 
3933*5113495bSYour Name /**
3934*5113495bSYour Name  * target_if_is_center_freq_of_any_chan() - Check for center frequency
3935*5113495bSYour Name  * @pdev: Pointer to pdev object
3936*5113495bSYour Name  * @chan_freq: Center frequency of a WLAN channel
3937*5113495bSYour Name  * @is_valid: Indicates whether given frequency is valid
3938*5113495bSYour Name  *
3939*5113495bSYour Name  * Helper routine to check whether given frequency is center frequency
3940*5113495bSYour Name  * of a WLAN channel
3941*5113495bSYour Name  *
3942*5113495bSYour Name  * Return: QDF_STATUS
3943*5113495bSYour Name  */
3944*5113495bSYour Name static QDF_STATUS
target_if_is_center_freq_of_any_chan(struct wlan_objmgr_pdev * pdev,uint32_t chan_freq,bool * is_valid)3945*5113495bSYour Name target_if_is_center_freq_of_any_chan(struct wlan_objmgr_pdev *pdev,
3946*5113495bSYour Name 				     uint32_t chan_freq,
3947*5113495bSYour Name 				     bool *is_valid)
3948*5113495bSYour Name {
3949*5113495bSYour Name 	struct regulatory_channel *cur_chan_list;
3950*5113495bSYour Name 	int i;
3951*5113495bSYour Name 
3952*5113495bSYour Name 	if (!pdev) {
3953*5113495bSYour Name 		spectral_err("pdev object is null");
3954*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
3955*5113495bSYour Name 	}
3956*5113495bSYour Name 
3957*5113495bSYour Name 	if (!is_valid) {
3958*5113495bSYour Name 		spectral_err("is valid argument is null");
3959*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
3960*5113495bSYour Name 	}
3961*5113495bSYour Name 
3962*5113495bSYour Name 	cur_chan_list = qdf_mem_malloc(NUM_CHANNELS * sizeof(*cur_chan_list));
3963*5113495bSYour Name 	if (!cur_chan_list)
3964*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
3965*5113495bSYour Name 
3966*5113495bSYour Name 	if (wlan_reg_get_current_chan_list(
3967*5113495bSYour Name 			pdev, cur_chan_list) != QDF_STATUS_SUCCESS) {
3968*5113495bSYour Name 		spectral_err("Failed to get cur_chan list");
3969*5113495bSYour Name 		qdf_mem_free(cur_chan_list);
3970*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
3971*5113495bSYour Name 	}
3972*5113495bSYour Name 
3973*5113495bSYour Name 	*is_valid = false;
3974*5113495bSYour Name 	for (i = 0; i < NUM_CHANNELS; i++) {
3975*5113495bSYour Name 		uint32_t flags;
3976*5113495bSYour Name 		uint32_t center_freq;
3977*5113495bSYour Name 
3978*5113495bSYour Name 		flags = cur_chan_list[i].chan_flags;
3979*5113495bSYour Name 		center_freq = cur_chan_list[i].center_freq;
3980*5113495bSYour Name 
3981*5113495bSYour Name 		if (!(flags & REGULATORY_CHAN_DISABLED) &&
3982*5113495bSYour Name 		    (center_freq == chan_freq)) {
3983*5113495bSYour Name 			*is_valid = true;
3984*5113495bSYour Name 			break;
3985*5113495bSYour Name 		}
3986*5113495bSYour Name 	}
3987*5113495bSYour Name 
3988*5113495bSYour Name 	qdf_mem_free(cur_chan_list);
3989*5113495bSYour Name 
3990*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
3991*5113495bSYour Name }
3992*5113495bSYour Name 
3993*5113495bSYour Name /**
3994*5113495bSYour Name  * target_if_calculate_center_freq() - find center frequency of agile span
3995*5113495bSYour Name  * @spectral: Pointer to Spectral object
3996*5113495bSYour Name  * @ch_width: Channel width array
3997*5113495bSYour Name  * @chan_freq: Center frequency of a WLAN channel
3998*5113495bSYour Name  * @center_freq: Pointer to center frequency
3999*5113495bSYour Name  *
4000*5113495bSYour Name  * Helper routine to find the center frequency of the agile span from
4001*5113495bSYour Name  * a WLAN channel center frequency
4002*5113495bSYour Name  *
4003*5113495bSYour Name  * Return: QDF_STATUS
4004*5113495bSYour Name  */
4005*5113495bSYour Name static QDF_STATUS
target_if_calculate_center_freq(struct target_if_spectral * spectral,enum phy_ch_width * ch_width,uint16_t chan_freq,uint16_t * center_freq)4006*5113495bSYour Name target_if_calculate_center_freq(struct target_if_spectral *spectral,
4007*5113495bSYour Name 				enum phy_ch_width *ch_width,
4008*5113495bSYour Name 				uint16_t chan_freq,
4009*5113495bSYour Name 				uint16_t *center_freq)
4010*5113495bSYour Name {
4011*5113495bSYour Name 	enum phy_ch_width agile_ch_width;
4012*5113495bSYour Name 
4013*5113495bSYour Name 	if (!spectral) {
4014*5113495bSYour Name 		spectral_err("spectral target if object is null");
4015*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4016*5113495bSYour Name 	}
4017*5113495bSYour Name 
4018*5113495bSYour Name 	if (!ch_width) {
4019*5113495bSYour Name 		spectral_err("Channel width array is null");
4020*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
4021*5113495bSYour Name 	}
4022*5113495bSYour Name 	agile_ch_width = ch_width[SPECTRAL_SCAN_MODE_AGILE];
4023*5113495bSYour Name 
4024*5113495bSYour Name 	if (!center_freq) {
4025*5113495bSYour Name 		spectral_err("center_freq argument is null");
4026*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4027*5113495bSYour Name 	}
4028*5113495bSYour Name 
4029*5113495bSYour Name 	if (agile_ch_width == CH_WIDTH_20MHZ) {
4030*5113495bSYour Name 		*center_freq = chan_freq;
4031*5113495bSYour Name 	} else {
4032*5113495bSYour Name 		uint16_t start_freq;
4033*5113495bSYour Name 		uint16_t end_freq;
4034*5113495bSYour Name 		const struct bonded_channel_freq *bonded_chan_ptr = NULL;
4035*5113495bSYour Name 		enum channel_state state;
4036*5113495bSYour Name 
4037*5113495bSYour Name 		state = wlan_reg_get_5g_bonded_channel_and_state_for_pwrmode
4038*5113495bSYour Name 			(spectral->pdev_obj, chan_freq, agile_ch_width,
4039*5113495bSYour Name 			 &bonded_chan_ptr, REG_CURRENT_PWR_MODE,
4040*5113495bSYour Name 			 NO_SCHANS_PUNC);
4041*5113495bSYour Name 		if (state == CHANNEL_STATE_DISABLE ||
4042*5113495bSYour Name 		    state == CHANNEL_STATE_INVALID) {
4043*5113495bSYour Name 			spectral_err("Channel state is disable or invalid");
4044*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
4045*5113495bSYour Name 		}
4046*5113495bSYour Name 		if (!bonded_chan_ptr) {
4047*5113495bSYour Name 			spectral_err("Bonded channel is not found");
4048*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
4049*5113495bSYour Name 		}
4050*5113495bSYour Name 		start_freq = bonded_chan_ptr->start_freq;
4051*5113495bSYour Name 		end_freq = bonded_chan_ptr->end_freq;
4052*5113495bSYour Name 		*center_freq = (start_freq + end_freq) >> 1;
4053*5113495bSYour Name 	}
4054*5113495bSYour Name 
4055*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
4056*5113495bSYour Name }
4057*5113495bSYour Name 
4058*5113495bSYour Name /**
4059*5113495bSYour Name  * target_if_validate_center_freq() - validate agile center frequency
4060*5113495bSYour Name  * @spectral: Pointer to Spectral object
4061*5113495bSYour Name  * @ch_width: Channel width array
4062*5113495bSYour Name  * @center_freq: User provided agile span center frequency
4063*5113495bSYour Name  * @is_valid: Indicates whether agile span center frequency is valid
4064*5113495bSYour Name  *
4065*5113495bSYour Name  * Helper routine to validate user provided agile center frequency
4066*5113495bSYour Name  *
4067*5113495bSYour Name  * Return: QDF_STATUS
4068*5113495bSYour Name  */
4069*5113495bSYour Name static QDF_STATUS
target_if_validate_center_freq(struct target_if_spectral * spectral,enum phy_ch_width * ch_width,uint16_t center_freq,bool * is_valid)4070*5113495bSYour Name target_if_validate_center_freq(struct target_if_spectral *spectral,
4071*5113495bSYour Name 			       enum phy_ch_width *ch_width,
4072*5113495bSYour Name 			       uint16_t center_freq,
4073*5113495bSYour Name 			       bool *is_valid)
4074*5113495bSYour Name {
4075*5113495bSYour Name 	enum phy_ch_width agile_ch_width;
4076*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev;
4077*5113495bSYour Name 	QDF_STATUS status;
4078*5113495bSYour Name 
4079*5113495bSYour Name 	if (!spectral) {
4080*5113495bSYour Name 		spectral_err("spectral target if object is null");
4081*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4082*5113495bSYour Name 	}
4083*5113495bSYour Name 
4084*5113495bSYour Name 	if (!ch_width) {
4085*5113495bSYour Name 		spectral_err("channel width array is null");
4086*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
4087*5113495bSYour Name 	}
4088*5113495bSYour Name 	agile_ch_width = ch_width[SPECTRAL_SCAN_MODE_AGILE];
4089*5113495bSYour Name 
4090*5113495bSYour Name 	if (!is_valid) {
4091*5113495bSYour Name 		spectral_err("is_valid argument is null");
4092*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4093*5113495bSYour Name 	}
4094*5113495bSYour Name 
4095*5113495bSYour Name 	pdev = spectral->pdev_obj;
4096*5113495bSYour Name 
4097*5113495bSYour Name 	if (agile_ch_width == CH_WIDTH_20MHZ) {
4098*5113495bSYour Name 		status = target_if_is_center_freq_of_any_chan
4099*5113495bSYour Name 				(pdev, center_freq, is_valid);
4100*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status))
4101*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
4102*5113495bSYour Name 	} else {
4103*5113495bSYour Name 		uint16_t start_freq;
4104*5113495bSYour Name 		uint16_t end_freq;
4105*5113495bSYour Name 		const struct bonded_channel_freq *bonded_chan_ptr = NULL;
4106*5113495bSYour Name 		bool is_chan;
4107*5113495bSYour Name 
4108*5113495bSYour Name 		status = target_if_is_center_freq_of_any_chan
4109*5113495bSYour Name 				(pdev, center_freq + FREQ_OFFSET_10MHZ,
4110*5113495bSYour Name 				 &is_chan);
4111*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status))
4112*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
4113*5113495bSYour Name 
4114*5113495bSYour Name 		if (is_chan) {
4115*5113495bSYour Name 			uint32_t calulated_center_freq;
4116*5113495bSYour Name 			enum channel_state st;
4117*5113495bSYour Name 
4118*5113495bSYour Name 			st =
4119*5113495bSYour Name 			    wlan_reg_get_5g_bonded_channel_and_state_for_pwrmode
4120*5113495bSYour Name 				(pdev, center_freq + FREQ_OFFSET_10MHZ,
4121*5113495bSYour Name 				 agile_ch_width,
4122*5113495bSYour Name 				 &bonded_chan_ptr,
4123*5113495bSYour Name 				 REG_CURRENT_PWR_MODE,
4124*5113495bSYour Name 				 NO_SCHANS_PUNC);
4125*5113495bSYour Name 			if (st == CHANNEL_STATE_DISABLE ||
4126*5113495bSYour Name 			    st == CHANNEL_STATE_INVALID) {
4127*5113495bSYour Name 				spectral_err("Channel state disable/invalid");
4128*5113495bSYour Name 				return QDF_STATUS_E_FAILURE;
4129*5113495bSYour Name 			}
4130*5113495bSYour Name 			if (!bonded_chan_ptr) {
4131*5113495bSYour Name 				spectral_err("Bonded channel is not found");
4132*5113495bSYour Name 				return QDF_STATUS_E_FAILURE;
4133*5113495bSYour Name 			}
4134*5113495bSYour Name 			start_freq = bonded_chan_ptr->start_freq;
4135*5113495bSYour Name 			end_freq = bonded_chan_ptr->end_freq;
4136*5113495bSYour Name 			calulated_center_freq = (start_freq + end_freq) >> 1;
4137*5113495bSYour Name 			*is_valid = (center_freq == calulated_center_freq);
4138*5113495bSYour Name 		} else {
4139*5113495bSYour Name 			*is_valid = false;
4140*5113495bSYour Name 		}
4141*5113495bSYour Name 	}
4142*5113495bSYour Name 
4143*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
4144*5113495bSYour Name }
4145*5113495bSYour Name 
4146*5113495bSYour Name /**
4147*5113495bSYour Name  * target_if_is_agile_span_overlap_with_operating_span() - Helper routine to
4148*5113495bSYour Name  * check whether agile span overlaps with current operating band.
4149*5113495bSYour Name  *
4150*5113495bSYour Name  * @spectral: Pointer to Spectral object
4151*5113495bSYour Name  * @ch_width: Channel width array
4152*5113495bSYour Name  * @center_freq: Agile span center frequency
4153*5113495bSYour Name  * @is_overlapping: Indicates whether Agile span overlaps with operating span
4154*5113495bSYour Name  *
4155*5113495bSYour Name  * Helper routine to check whether agile span overlaps with current
4156*5113495bSYour Name  * operating band.
4157*5113495bSYour Name  *
4158*5113495bSYour Name  * Return: QDF_STATUS
4159*5113495bSYour Name  */
4160*5113495bSYour Name static QDF_STATUS
target_if_is_agile_span_overlap_with_operating_span(struct target_if_spectral * spectral,enum phy_ch_width * ch_width,struct spectral_config_frequency * center_freq,bool * is_overlapping)4161*5113495bSYour Name target_if_is_agile_span_overlap_with_operating_span
4162*5113495bSYour Name 			(struct target_if_spectral *spectral,
4163*5113495bSYour Name 			 enum phy_ch_width *ch_width,
4164*5113495bSYour Name 			 struct spectral_config_frequency *center_freq,
4165*5113495bSYour Name 			 bool *is_overlapping)
4166*5113495bSYour Name {
4167*5113495bSYour Name 	enum phy_ch_width op_ch_width;
4168*5113495bSYour Name 	enum phy_ch_width agile_ch_width;
4169*5113495bSYour Name 	const struct bonded_channel_freq *bonded_chan_ptr = NULL;
4170*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
4171*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev;
4172*5113495bSYour Name 	int16_t chan_freq;
4173*5113495bSYour Name 	uint32_t op_start_freq;
4174*5113495bSYour Name 	uint32_t op_end_freq;
4175*5113495bSYour Name 	uint32_t agile_start_freq;
4176*5113495bSYour Name 	uint32_t agile_end_freq;
4177*5113495bSYour Name 	uint32_t cfreq2;
4178*5113495bSYour Name 
4179*5113495bSYour Name 	if (!spectral) {
4180*5113495bSYour Name 		spectral_err("spectral object is NULL");
4181*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4182*5113495bSYour Name 	}
4183*5113495bSYour Name 
4184*5113495bSYour Name 	pdev  = spectral->pdev_obj;
4185*5113495bSYour Name 	if (!pdev) {
4186*5113495bSYour Name 		spectral_err("pdev object is NULL");
4187*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4188*5113495bSYour Name 	}
4189*5113495bSYour Name 
4190*5113495bSYour Name 	if (!ch_width) {
4191*5113495bSYour Name 		spectral_err("channel width array is null");
4192*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4193*5113495bSYour Name 	}
4194*5113495bSYour Name 	op_ch_width = ch_width[SPECTRAL_SCAN_MODE_NORMAL];
4195*5113495bSYour Name 	if (op_ch_width == CH_WIDTH_INVALID) {
4196*5113495bSYour Name 		spectral_err("Invalid channel width");
4197*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
4198*5113495bSYour Name 	}
4199*5113495bSYour Name 	agile_ch_width = ch_width[SPECTRAL_SCAN_MODE_AGILE];
4200*5113495bSYour Name 	if (agile_ch_width == CH_WIDTH_INVALID) {
4201*5113495bSYour Name 		spectral_err("Invalid channel width");
4202*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
4203*5113495bSYour Name 	}
4204*5113495bSYour Name 
4205*5113495bSYour Name 	if (!is_overlapping) {
4206*5113495bSYour Name 		spectral_err("Argument(is_overlapping) is NULL");
4207*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4208*5113495bSYour Name 	}
4209*5113495bSYour Name 	*is_overlapping = false;
4210*5113495bSYour Name 
4211*5113495bSYour Name 	vdev = target_if_spectral_get_vdev(spectral, SPECTRAL_SCAN_MODE_AGILE);
4212*5113495bSYour Name 	if (!vdev) {
4213*5113495bSYour Name 		spectral_err("vdev is NULL");
4214*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4215*5113495bSYour Name 	}
4216*5113495bSYour Name 	chan_freq = target_if_vdev_get_chan_freq(vdev);
4217*5113495bSYour Name 	cfreq2 = target_if_vdev_get_chan_freq_seg2(vdev);
4218*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
4219*5113495bSYour Name 	if (cfreq2 < 0) {
4220*5113495bSYour Name 		spectral_err("cfreq2 is invalid");
4221*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4222*5113495bSYour Name 	}
4223*5113495bSYour Name 
4224*5113495bSYour Name 	if (op_ch_width == CH_WIDTH_20MHZ) {
4225*5113495bSYour Name 		op_start_freq = chan_freq - FREQ_OFFSET_10MHZ;
4226*5113495bSYour Name 		op_end_freq = chan_freq + FREQ_OFFSET_10MHZ;
4227*5113495bSYour Name 	} else {
4228*5113495bSYour Name 		enum channel_state state;
4229*5113495bSYour Name 
4230*5113495bSYour Name 		state = wlan_reg_get_5g_bonded_channel_and_state_for_pwrmode
4231*5113495bSYour Name 			(pdev, chan_freq, op_ch_width, &bonded_chan_ptr,
4232*5113495bSYour Name 			 REG_CURRENT_PWR_MODE, NO_SCHANS_PUNC);
4233*5113495bSYour Name 		if (state == CHANNEL_STATE_DISABLE ||
4234*5113495bSYour Name 		    state == CHANNEL_STATE_INVALID) {
4235*5113495bSYour Name 			spectral_err("Channel state is disable or invalid");
4236*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
4237*5113495bSYour Name 		}
4238*5113495bSYour Name 		if (!bonded_chan_ptr) {
4239*5113495bSYour Name 			spectral_err("Bonded channel is not found");
4240*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
4241*5113495bSYour Name 		}
4242*5113495bSYour Name 		op_start_freq = bonded_chan_ptr->start_freq - FREQ_OFFSET_10MHZ;
4243*5113495bSYour Name 		op_end_freq = bonded_chan_ptr->end_freq - FREQ_OFFSET_10MHZ;
4244*5113495bSYour Name 	}
4245*5113495bSYour Name 
4246*5113495bSYour Name 	if (agile_ch_width == CH_WIDTH_80P80MHZ) {
4247*5113495bSYour Name 		agile_start_freq = center_freq->cfreq1 - FREQ_OFFSET_40MHZ;
4248*5113495bSYour Name 		agile_end_freq = center_freq->cfreq1 + FREQ_OFFSET_40MHZ;
4249*5113495bSYour Name 		if (agile_end_freq > op_start_freq &&
4250*5113495bSYour Name 		    op_end_freq > agile_start_freq)
4251*5113495bSYour Name 			*is_overlapping = true;
4252*5113495bSYour Name 
4253*5113495bSYour Name 		agile_start_freq = center_freq->cfreq2 - FREQ_OFFSET_40MHZ;
4254*5113495bSYour Name 		agile_end_freq = center_freq->cfreq2 + FREQ_OFFSET_40MHZ;
4255*5113495bSYour Name 		if (agile_end_freq > op_start_freq &&
4256*5113495bSYour Name 		    op_end_freq > agile_start_freq)
4257*5113495bSYour Name 			*is_overlapping = true;
4258*5113495bSYour Name 	} else {
4259*5113495bSYour Name 		agile_start_freq = center_freq->cfreq1 -
4260*5113495bSYour Name 				(wlan_reg_get_bw_value(agile_ch_width) >> 1);
4261*5113495bSYour Name 		agile_end_freq = center_freq->cfreq1 +
4262*5113495bSYour Name 				(wlan_reg_get_bw_value(agile_ch_width) >> 1);
4263*5113495bSYour Name 		if (agile_end_freq > op_start_freq &&
4264*5113495bSYour Name 		    op_end_freq > agile_start_freq)
4265*5113495bSYour Name 			*is_overlapping = true;
4266*5113495bSYour Name 	}
4267*5113495bSYour Name 
4268*5113495bSYour Name 	if (op_ch_width == CH_WIDTH_80P80MHZ) {
4269*5113495bSYour Name 		uint32_t sec80_start_feq;
4270*5113495bSYour Name 		uint32_t sec80_end_freq;
4271*5113495bSYour Name 
4272*5113495bSYour Name 		sec80_start_feq = cfreq2 - FREQ_OFFSET_40MHZ;
4273*5113495bSYour Name 		sec80_end_freq = cfreq2 + FREQ_OFFSET_40MHZ;
4274*5113495bSYour Name 
4275*5113495bSYour Name 		if (agile_ch_width == CH_WIDTH_80P80MHZ) {
4276*5113495bSYour Name 			agile_start_freq =
4277*5113495bSYour Name 					center_freq->cfreq1 - FREQ_OFFSET_40MHZ;
4278*5113495bSYour Name 			agile_end_freq =
4279*5113495bSYour Name 					center_freq->cfreq1 + FREQ_OFFSET_40MHZ;
4280*5113495bSYour Name 			if (agile_end_freq > sec80_start_feq &&
4281*5113495bSYour Name 			    sec80_end_freq > agile_start_freq)
4282*5113495bSYour Name 				*is_overlapping = true;
4283*5113495bSYour Name 
4284*5113495bSYour Name 			agile_start_freq =
4285*5113495bSYour Name 					center_freq->cfreq2 - FREQ_OFFSET_40MHZ;
4286*5113495bSYour Name 			agile_end_freq =
4287*5113495bSYour Name 					center_freq->cfreq2 + FREQ_OFFSET_40MHZ;
4288*5113495bSYour Name 			if (agile_end_freq > sec80_start_feq &&
4289*5113495bSYour Name 			    sec80_end_freq > agile_start_freq)
4290*5113495bSYour Name 				*is_overlapping = true;
4291*5113495bSYour Name 		} else {
4292*5113495bSYour Name 			agile_start_freq = center_freq->cfreq1 -
4293*5113495bSYour Name 				(wlan_reg_get_bw_value(agile_ch_width) >> 1);
4294*5113495bSYour Name 			agile_end_freq = center_freq->cfreq1 +
4295*5113495bSYour Name 				(wlan_reg_get_bw_value(agile_ch_width) >> 1);
4296*5113495bSYour Name 			if (agile_end_freq > sec80_start_feq &&
4297*5113495bSYour Name 			    sec80_end_freq > agile_start_freq)
4298*5113495bSYour Name 				*is_overlapping = true;
4299*5113495bSYour Name 		}
4300*5113495bSYour Name 	}
4301*5113495bSYour Name 
4302*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
4303*5113495bSYour Name }
4304*5113495bSYour Name 
4305*5113495bSYour Name /**
4306*5113495bSYour Name  * target_if_spectral_populate_chwidth() - Helper routine to
4307*5113495bSYour Name  * populate channel width for different Spectral modes
4308*5113495bSYour Name  *
4309*5113495bSYour Name  * @spectral: Pointer to Spectral object
4310*5113495bSYour Name  * @ch_width: Channel width array
4311*5113495bSYour Name  * @is_80_80_agile: Indicates whether 80+80 agile scan is requested
4312*5113495bSYour Name  *
4313*5113495bSYour Name  * Helper routine to populate channel width for different Spectral modes
4314*5113495bSYour Name  *
4315*5113495bSYour Name  * Return: QDF_STATUS
4316*5113495bSYour Name  */
4317*5113495bSYour Name static QDF_STATUS
target_if_spectral_populate_chwidth(struct target_if_spectral * spectral,enum phy_ch_width * ch_width,bool is_80_80_agile)4318*5113495bSYour Name target_if_spectral_populate_chwidth(struct target_if_spectral *spectral,
4319*5113495bSYour Name 				    enum phy_ch_width *ch_width,
4320*5113495bSYour Name 				    bool is_80_80_agile)
4321*5113495bSYour Name {
4322*5113495bSYour Name 	enum spectral_scan_mode smode;
4323*5113495bSYour Name 
4324*5113495bSYour Name 	if (!spectral) {
4325*5113495bSYour Name 		spectral_err("Spectral variable is null");
4326*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
4327*5113495bSYour Name 	}
4328*5113495bSYour Name 
4329*5113495bSYour Name 	smode = SPECTRAL_SCAN_MODE_NORMAL;
4330*5113495bSYour Name 	for (; smode < SPECTRAL_SCAN_MODE_MAX; ++smode) {
4331*5113495bSYour Name 		/* If user has configured sscan bandwidth, use it */
4332*5113495bSYour Name 		if (spectral->sscan_width_configured[smode]) {
4333*5113495bSYour Name 			ch_width[smode] = spectral->params[smode].ss_bandwidth;
4334*5113495bSYour Name 		} else {
4335*5113495bSYour Name 			/* Otherwise, derive the default sscan bandwidth */
4336*5113495bSYour Name 			ch_width[smode] = get_default_sscan_bw(spectral, smode,
4337*5113495bSYour Name 							       is_80_80_agile);
4338*5113495bSYour Name 			if (ch_width[smode] >= CH_WIDTH_INVALID) {
4339*5113495bSYour Name 				spectral_err("Invalid sscan BW %u",
4340*5113495bSYour Name 					     ch_width[smode]);
4341*5113495bSYour Name 				return QDF_STATUS_E_FAILURE;
4342*5113495bSYour Name 			}
4343*5113495bSYour Name 			spectral->params[smode].ss_bandwidth = ch_width[smode];
4344*5113495bSYour Name 		}
4345*5113495bSYour Name 	}
4346*5113495bSYour Name 
4347*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
4348*5113495bSYour Name }
4349*5113495bSYour Name 
4350*5113495bSYour Name /**
4351*5113495bSYour Name  * target_if_spectral_is_valid_80p80_freq() - API to check whether given
4352*5113495bSYour Name  * (cfreq1, cfreq2) pair forms a valid 80+80 combination
4353*5113495bSYour Name  * @pdev: pointer to pdev
4354*5113495bSYour Name  * @cfreq1: center frequency 1
4355*5113495bSYour Name  * @cfreq2: center frequency 2
4356*5113495bSYour Name  * @is_valid: Indicates weather the frequency is valid
4357*5113495bSYour Name  *
4358*5113495bSYour Name  * API to check whether given (cfreq1, cfreq2) pair forms a valid 80+80
4359*5113495bSYour Name  * combination
4360*5113495bSYour Name  *
4361*5113495bSYour Name  * Return: QDF_Status
4362*5113495bSYour Name  */
4363*5113495bSYour Name static QDF_STATUS
target_if_spectral_is_valid_80p80_freq(struct wlan_objmgr_pdev * pdev,uint32_t cfreq1,uint32_t cfreq2,bool * is_valid)4364*5113495bSYour Name target_if_spectral_is_valid_80p80_freq(struct wlan_objmgr_pdev *pdev,
4365*5113495bSYour Name 				       uint32_t cfreq1, uint32_t cfreq2,
4366*5113495bSYour Name 				       bool *is_valid)
4367*5113495bSYour Name {
4368*5113495bSYour Name 	struct ch_params ch_params = {0};
4369*5113495bSYour Name 	enum channel_state chan_state1;
4370*5113495bSYour Name 	enum channel_state chan_state2;
4371*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
4372*5113495bSYour Name 	struct ch_params temp_params = {0};
4373*5113495bSYour Name 
4374*5113495bSYour Name 	if (!is_valid) {
4375*5113495bSYour Name 		spectral_err("Argument(is_valid) is null");
4376*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
4377*5113495bSYour Name 	}
4378*5113495bSYour Name 
4379*5113495bSYour Name 	if (!pdev) {
4380*5113495bSYour Name 		spectral_err("pdev is null.");
4381*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
4382*5113495bSYour Name 	}
4383*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
4384*5113495bSYour Name 	if (!psoc) {
4385*5113495bSYour Name 		spectral_err("psoc is null.");
4386*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
4387*5113495bSYour Name 	}
4388*5113495bSYour Name 
4389*5113495bSYour Name 	/* In restricted 80P80 MHz enabled, only one 80+80 MHz
4390*5113495bSYour Name 	 * channel is supported with cfreq=5690 and cfreq=5775.
4391*5113495bSYour Name 	 */
4392*5113495bSYour Name 	if (wlan_psoc_nif_fw_ext_cap_get(
4393*5113495bSYour Name 				psoc, WLAN_SOC_RESTRICTED_80P80_SUPPORT)) {
4394*5113495bSYour Name 		*is_valid = CHAN_WITHIN_RESTRICTED_80P80(cfreq1, cfreq2);
4395*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
4396*5113495bSYour Name 	}
4397*5113495bSYour Name 
4398*5113495bSYour Name 	ch_params.center_freq_seg1 = wlan_reg_freq_to_chan(pdev, cfreq2);
4399*5113495bSYour Name 	ch_params.mhz_freq_seg1 = cfreq2;
4400*5113495bSYour Name 	ch_params.ch_width = CH_WIDTH_80P80MHZ;
4401*5113495bSYour Name 	wlan_reg_set_channel_params_for_pwrmode(
4402*5113495bSYour Name 					pdev,
4403*5113495bSYour Name 					cfreq1 - FREQ_OFFSET_10MHZ,
4404*5113495bSYour Name 					0,
4405*5113495bSYour Name 					&ch_params,
4406*5113495bSYour Name 					REG_CURRENT_PWR_MODE);
4407*5113495bSYour Name 
4408*5113495bSYour Name 	if (ch_params.ch_width != CH_WIDTH_80P80MHZ) {
4409*5113495bSYour Name 		*is_valid = false;
4410*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
4411*5113495bSYour Name 	}
4412*5113495bSYour Name 
4413*5113495bSYour Name 	if (ch_params.mhz_freq_seg0 != cfreq1 ||
4414*5113495bSYour Name 	    ch_params.mhz_freq_seg1 != cfreq2) {
4415*5113495bSYour Name 		*is_valid = false;
4416*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
4417*5113495bSYour Name 	}
4418*5113495bSYour Name 
4419*5113495bSYour Name 	temp_params.ch_width = CH_WIDTH_80MHZ;
4420*5113495bSYour Name 	chan_state1 = wlan_reg_get_5g_bonded_channel_state_for_pwrmode(
4421*5113495bSYour Name 				pdev,
4422*5113495bSYour Name 				ch_params.mhz_freq_seg0 - FREQ_OFFSET_10MHZ,
4423*5113495bSYour Name 				&temp_params,
4424*5113495bSYour Name 				REG_CURRENT_PWR_MODE);
4425*5113495bSYour Name 	if ((chan_state1 == CHANNEL_STATE_DISABLE) ||
4426*5113495bSYour Name 	    (chan_state1 == CHANNEL_STATE_INVALID)) {
4427*5113495bSYour Name 		*is_valid = false;
4428*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
4429*5113495bSYour Name 	}
4430*5113495bSYour Name 
4431*5113495bSYour Name 	temp_params.ch_width = CH_WIDTH_80MHZ;
4432*5113495bSYour Name 	chan_state2 = wlan_reg_get_5g_bonded_channel_state_for_pwrmode(
4433*5113495bSYour Name 				pdev,
4434*5113495bSYour Name 				ch_params.mhz_freq_seg1 - FREQ_OFFSET_10MHZ,
4435*5113495bSYour Name 				&temp_params,
4436*5113495bSYour Name 				REG_CURRENT_PWR_MODE);
4437*5113495bSYour Name 	if ((chan_state2 == CHANNEL_STATE_DISABLE) ||
4438*5113495bSYour Name 	    (chan_state2 == CHANNEL_STATE_INVALID)) {
4439*5113495bSYour Name 		*is_valid = false;
4440*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
4441*5113495bSYour Name 	}
4442*5113495bSYour Name 
4443*5113495bSYour Name 	if (abs(ch_params.mhz_freq_seg0 - ch_params.mhz_freq_seg1) <=
4444*5113495bSYour Name 	    FREQ_OFFSET_80MHZ) {
4445*5113495bSYour Name 		*is_valid = false;
4446*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
4447*5113495bSYour Name 	}
4448*5113495bSYour Name 
4449*5113495bSYour Name 	*is_valid = true;
4450*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
4451*5113495bSYour Name }
4452*5113495bSYour Name 
4453*5113495bSYour Name /**
4454*5113495bSYour Name  * _target_if_set_spectral_config() - Set spectral config
4455*5113495bSYour Name  * @spectral:       Pointer to spectral object
4456*5113495bSYour Name  * @param: Spectral parameter id and value
4457*5113495bSYour Name  * @smode: Spectral scan mode
4458*5113495bSYour Name  * @err: Spectral error code
4459*5113495bSYour Name  *
4460*5113495bSYour Name  * API to set spectral configurations
4461*5113495bSYour Name  *
4462*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
4463*5113495bSYour Name  */
4464*5113495bSYour Name static QDF_STATUS
_target_if_set_spectral_config(struct target_if_spectral * spectral,const struct spectral_cp_param * param,const enum spectral_scan_mode smode,enum spectral_cp_error_code * err)4465*5113495bSYour Name _target_if_set_spectral_config(struct target_if_spectral *spectral,
4466*5113495bSYour Name 			       const struct spectral_cp_param *param,
4467*5113495bSYour Name 			       const enum spectral_scan_mode smode,
4468*5113495bSYour Name 			       enum spectral_cp_error_code *err)
4469*5113495bSYour Name {
4470*5113495bSYour Name 	struct spectral_config params;
4471*5113495bSYour Name 	struct target_if_spectral_ops *p_sops;
4472*5113495bSYour Name 	struct spectral_config *sparams;
4473*5113495bSYour Name 	QDF_STATUS status;
4474*5113495bSYour Name 	bool is_overlapping;
4475*5113495bSYour Name 	uint16_t agile_cfreq;
4476*5113495bSYour Name 	bool is_valid_chan;
4477*5113495bSYour Name 	struct spectral_param_min_max *param_min_max;
4478*5113495bSYour Name 	enum phy_ch_width ch_width[SPECTRAL_SCAN_MODE_MAX];
4479*5113495bSYour Name 	enum spectral_scan_mode m;
4480*5113495bSYour Name 	struct spectral_config_frequency center_freq = {0};
4481*5113495bSYour Name 	bool is_bw_supported;
4482*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
4483*5113495bSYour Name 	enum phy_ch_width op_bw;
4484*5113495bSYour Name 
4485*5113495bSYour Name 	if (!err) {
4486*5113495bSYour Name 		spectral_err("Error code argument is null");
4487*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
4488*5113495bSYour Name 	}
4489*5113495bSYour Name 	*err = SPECTRAL_SCAN_ERR_INVALID;
4490*5113495bSYour Name 
4491*5113495bSYour Name 	if (!param) {
4492*5113495bSYour Name 		spectral_err("Parameter object is null");
4493*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4494*5113495bSYour Name 	}
4495*5113495bSYour Name 
4496*5113495bSYour Name 	if (!spectral) {
4497*5113495bSYour Name 		spectral_err("spectral object is NULL");
4498*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4499*5113495bSYour Name 	}
4500*5113495bSYour Name 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
4501*5113495bSYour Name 	param_min_max = &spectral->param_min_max;
4502*5113495bSYour Name 
4503*5113495bSYour Name 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
4504*5113495bSYour Name 		spectral_err("Invalid Spectral mode %u", smode);
4505*5113495bSYour Name 		*err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED;
4506*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4507*5113495bSYour Name 	}
4508*5113495bSYour Name 
4509*5113495bSYour Name 	sparams = &spectral->params[smode];
4510*5113495bSYour Name 	m = SPECTRAL_SCAN_MODE_NORMAL;
4511*5113495bSYour Name 	for (; m < SPECTRAL_SCAN_MODE_MAX; m++)
4512*5113495bSYour Name 		ch_width[m] = CH_WIDTH_INVALID;
4513*5113495bSYour Name 
4514*5113495bSYour Name 	if (!spectral->params_valid[smode]) {
4515*5113495bSYour Name 		target_if_spectral_info_read(spectral,
4516*5113495bSYour Name 					     smode,
4517*5113495bSYour Name 					     TARGET_IF_SPECTRAL_INFO_PARAMS,
4518*5113495bSYour Name 					     &spectral->params[smode],
4519*5113495bSYour Name 					     sizeof(spectral->params[smode]));
4520*5113495bSYour Name 		spectral->params_valid[smode] = true;
4521*5113495bSYour Name 	}
4522*5113495bSYour Name 
4523*5113495bSYour Name 	switch (param->id) {
4524*5113495bSYour Name 	case SPECTRAL_PARAM_FFT_PERIOD:
4525*5113495bSYour Name 		sparams->ss_fft_period = param->value;
4526*5113495bSYour Name 		break;
4527*5113495bSYour Name 	case SPECTRAL_PARAM_SCAN_PERIOD:
4528*5113495bSYour Name 		sparams->ss_period = param->value;
4529*5113495bSYour Name 		if (sparams->ss_recapture && ((sparams->ss_period <
4530*5113495bSYour Name 		    SPECTRAL_RECAPTURE_SCAN_PERIOD_THRESHOLD) ||
4531*5113495bSYour Name 		    (smode == SPECTRAL_SCAN_MODE_AGILE))) {
4532*5113495bSYour Name 			sparams->ss_recapture = false;
4533*5113495bSYour Name 			spectral_err("FFT recapture cannot be enabled due to scan period: %d us or spectral scan mode: %d",
4534*5113495bSYour Name 				     sparams->ss_period, smode);
4535*5113495bSYour Name 		}
4536*5113495bSYour Name 		break;
4537*5113495bSYour Name 	case SPECTRAL_PARAM_FFT_RECAPTURE:
4538*5113495bSYour Name 		if (param->value) {
4539*5113495bSYour Name 			if (sparams->ss_period >=
4540*5113495bSYour Name 			    SPECTRAL_RECAPTURE_SCAN_PERIOD_THRESHOLD &&
4541*5113495bSYour Name 			    smode == SPECTRAL_SCAN_MODE_NORMAL) {
4542*5113495bSYour Name 				sparams->ss_recapture = true;
4543*5113495bSYour Name 			} else {
4544*5113495bSYour Name 				spectral_err("FFT recapture cannot be enabled due to scan period: %d us or spectral scan mode: %d",
4545*5113495bSYour Name 					     sparams->ss_period, smode);
4546*5113495bSYour Name 				sparams->ss_recapture = false;
4547*5113495bSYour Name 			}
4548*5113495bSYour Name 		} else {
4549*5113495bSYour Name 			sparams->ss_recapture = false;
4550*5113495bSYour Name 		}
4551*5113495bSYour Name 		break;
4552*5113495bSYour Name 	case SPECTRAL_PARAM_SCAN_COUNT:
4553*5113495bSYour Name 		if (param->value > param_min_max->scan_count_max) {
4554*5113495bSYour Name 			*err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
4555*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
4556*5113495bSYour Name 		}
4557*5113495bSYour Name 		sparams->ss_count = param->value;
4558*5113495bSYour Name 		break;
4559*5113495bSYour Name 	case SPECTRAL_PARAM_SHORT_REPORT:
4560*5113495bSYour Name 		sparams->ss_short_report = (!!param->value) ? true : false;
4561*5113495bSYour Name 		break;
4562*5113495bSYour Name 	case SPECTRAL_PARAM_SPECT_PRI:
4563*5113495bSYour Name 		sparams->ss_spectral_pri = (!!param->value) ? true : false;
4564*5113495bSYour Name 		break;
4565*5113495bSYour Name 	case SPECTRAL_PARAM_FFT_SIZE:
4566*5113495bSYour Name 		status = target_if_spectral_populate_chwidth
4567*5113495bSYour Name 			(spectral, ch_width, spectral->params
4568*5113495bSYour Name 			 [SPECTRAL_SCAN_MODE_AGILE].ss_frequency.cfreq2 > 0);
4569*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status))
4570*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
4571*5113495bSYour Name 		if ((param->value < param_min_max->fft_size_min) ||
4572*5113495bSYour Name 		    (param->value > param_min_max->fft_size_max
4573*5113495bSYour Name 		    [ch_width[smode]])) {
4574*5113495bSYour Name 			*err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
4575*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
4576*5113495bSYour Name 		}
4577*5113495bSYour Name 		sparams->ss_fft_size = param->value;
4578*5113495bSYour Name 		break;
4579*5113495bSYour Name 	case SPECTRAL_PARAM_GC_ENA:
4580*5113495bSYour Name 		sparams->ss_gc_ena = !!param->value;
4581*5113495bSYour Name 		break;
4582*5113495bSYour Name 	case SPECTRAL_PARAM_RESTART_ENA:
4583*5113495bSYour Name 		sparams->ss_restart_ena = !!param->value;
4584*5113495bSYour Name 		break;
4585*5113495bSYour Name 	case SPECTRAL_PARAM_NOISE_FLOOR_REF:
4586*5113495bSYour Name 		sparams->ss_noise_floor_ref = param->value;
4587*5113495bSYour Name 		break;
4588*5113495bSYour Name 	case SPECTRAL_PARAM_INIT_DELAY:
4589*5113495bSYour Name 		sparams->ss_init_delay = param->value;
4590*5113495bSYour Name 		break;
4591*5113495bSYour Name 	case SPECTRAL_PARAM_NB_TONE_THR:
4592*5113495bSYour Name 		sparams->ss_nb_tone_thr = param->value;
4593*5113495bSYour Name 		break;
4594*5113495bSYour Name 	case SPECTRAL_PARAM_STR_BIN_THR:
4595*5113495bSYour Name 		sparams->ss_str_bin_thr = param->value;
4596*5113495bSYour Name 		break;
4597*5113495bSYour Name 	case SPECTRAL_PARAM_WB_RPT_MODE:
4598*5113495bSYour Name 		sparams->ss_wb_rpt_mode = !!param->value;
4599*5113495bSYour Name 		break;
4600*5113495bSYour Name 	case SPECTRAL_PARAM_RSSI_RPT_MODE:
4601*5113495bSYour Name 		sparams->ss_rssi_rpt_mode = !!param->value;
4602*5113495bSYour Name 		break;
4603*5113495bSYour Name 	case SPECTRAL_PARAM_RSSI_THR:
4604*5113495bSYour Name 		sparams->ss_rssi_thr = param->value;
4605*5113495bSYour Name 		break;
4606*5113495bSYour Name 	case SPECTRAL_PARAM_PWR_FORMAT:
4607*5113495bSYour Name 		sparams->ss_pwr_format = !!param->value;
4608*5113495bSYour Name 		break;
4609*5113495bSYour Name 	case SPECTRAL_PARAM_RPT_MODE:
4610*5113495bSYour Name 		if ((param->value < SPECTRAL_PARAM_RPT_MODE_MIN) ||
4611*5113495bSYour Name 		    (param->value > SPECTRAL_PARAM_RPT_MODE_MAX)) {
4612*5113495bSYour Name 			*err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
4613*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
4614*5113495bSYour Name 		}
4615*5113495bSYour Name 		sparams->ss_rpt_mode = param->value;
4616*5113495bSYour Name 		break;
4617*5113495bSYour Name 	case SPECTRAL_PARAM_BIN_SCALE:
4618*5113495bSYour Name 		sparams->ss_bin_scale = param->value;
4619*5113495bSYour Name 		break;
4620*5113495bSYour Name 	case SPECTRAL_PARAM_DBM_ADJ:
4621*5113495bSYour Name 		sparams->ss_dbm_adj = !!param->value;
4622*5113495bSYour Name 		break;
4623*5113495bSYour Name 	case SPECTRAL_PARAM_CHN_MASK:
4624*5113495bSYour Name 		sparams->ss_chn_mask = param->value;
4625*5113495bSYour Name 		break;
4626*5113495bSYour Name 	case SPECTRAL_PARAM_FREQUENCY:
4627*5113495bSYour Name 		status = target_if_spectral_populate_chwidth(
4628*5113495bSYour Name 				spectral, ch_width, param->freq.cfreq2 > 0);
4629*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
4630*5113495bSYour Name 			spectral_err("Failed to populate channel width");
4631*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
4632*5113495bSYour Name 		}
4633*5113495bSYour Name 
4634*5113495bSYour Name 		if (ch_width[smode] != CH_WIDTH_80P80MHZ &&
4635*5113495bSYour Name 		    param->freq.cfreq2) {
4636*5113495bSYour Name 			*err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
4637*5113495bSYour Name 			spectral_err("Non zero cfreq2 expected for 80p80 only");
4638*5113495bSYour Name 			return QDF_STATUS_E_INVAL;
4639*5113495bSYour Name 		}
4640*5113495bSYour Name 
4641*5113495bSYour Name 		if (ch_width[smode] == CH_WIDTH_80P80MHZ &&
4642*5113495bSYour Name 		    !param->freq.cfreq2) {
4643*5113495bSYour Name 			*err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
4644*5113495bSYour Name 			spectral_err("Non zero cfreq2 expected for 80p80");
4645*5113495bSYour Name 			return QDF_STATUS_E_INVAL;
4646*5113495bSYour Name 		}
4647*5113495bSYour Name 
4648*5113495bSYour Name 		status = target_if_is_center_freq_of_any_chan
4649*5113495bSYour Name 				(spectral->pdev_obj, param->freq.cfreq1,
4650*5113495bSYour Name 				 &is_valid_chan);
4651*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status))
4652*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
4653*5113495bSYour Name 
4654*5113495bSYour Name 		if (is_valid_chan) {
4655*5113495bSYour Name 			status = target_if_calculate_center_freq(
4656*5113495bSYour Name 							spectral, ch_width,
4657*5113495bSYour Name 							param->freq.cfreq1,
4658*5113495bSYour Name 							&agile_cfreq);
4659*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(status)) {
4660*5113495bSYour Name 				*err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
4661*5113495bSYour Name 				return QDF_STATUS_E_FAILURE;
4662*5113495bSYour Name 			}
4663*5113495bSYour Name 		} else {
4664*5113495bSYour Name 			bool is_valid_agile_cfreq;
4665*5113495bSYour Name 
4666*5113495bSYour Name 			status = target_if_validate_center_freq
4667*5113495bSYour Name 				(spectral, ch_width, param->freq.cfreq1,
4668*5113495bSYour Name 				 &is_valid_agile_cfreq);
4669*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(status))
4670*5113495bSYour Name 				return QDF_STATUS_E_FAILURE;
4671*5113495bSYour Name 
4672*5113495bSYour Name 			if (!is_valid_agile_cfreq) {
4673*5113495bSYour Name 				*err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
4674*5113495bSYour Name 				spectral_err("Invalid agile center frequency");
4675*5113495bSYour Name 				return QDF_STATUS_E_FAILURE;
4676*5113495bSYour Name 			}
4677*5113495bSYour Name 
4678*5113495bSYour Name 			agile_cfreq = param->freq.cfreq1;
4679*5113495bSYour Name 		}
4680*5113495bSYour Name 		center_freq.cfreq1 = agile_cfreq;
4681*5113495bSYour Name 
4682*5113495bSYour Name 		if (ch_width[smode] == CH_WIDTH_80P80MHZ) {
4683*5113495bSYour Name 			status = target_if_is_center_freq_of_any_chan
4684*5113495bSYour Name 					(spectral->pdev_obj, param->freq.cfreq2,
4685*5113495bSYour Name 					 &is_valid_chan);
4686*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(status))
4687*5113495bSYour Name 				return QDF_STATUS_E_FAILURE;
4688*5113495bSYour Name 
4689*5113495bSYour Name 			if (is_valid_chan) {
4690*5113495bSYour Name 				status = target_if_calculate_center_freq(
4691*5113495bSYour Name 						spectral, ch_width,
4692*5113495bSYour Name 						param->freq.cfreq2,
4693*5113495bSYour Name 						&agile_cfreq);
4694*5113495bSYour Name 				if (QDF_IS_STATUS_ERROR(status)) {
4695*5113495bSYour Name 					*err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
4696*5113495bSYour Name 					return QDF_STATUS_E_FAILURE;
4697*5113495bSYour Name 				}
4698*5113495bSYour Name 			} else {
4699*5113495bSYour Name 				bool is_valid_agile_cfreq;
4700*5113495bSYour Name 
4701*5113495bSYour Name 				status = target_if_validate_center_freq
4702*5113495bSYour Name 					(spectral, ch_width, param->freq.cfreq2,
4703*5113495bSYour Name 					 &is_valid_agile_cfreq);
4704*5113495bSYour Name 				if (QDF_IS_STATUS_ERROR(status))
4705*5113495bSYour Name 					return QDF_STATUS_E_FAILURE;
4706*5113495bSYour Name 
4707*5113495bSYour Name 				if (!is_valid_agile_cfreq) {
4708*5113495bSYour Name 					*err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
4709*5113495bSYour Name 					spectral_err("Invalid agile center frequency");
4710*5113495bSYour Name 					return QDF_STATUS_E_FAILURE;
4711*5113495bSYour Name 				}
4712*5113495bSYour Name 
4713*5113495bSYour Name 				agile_cfreq = param->freq.cfreq2;
4714*5113495bSYour Name 			}
4715*5113495bSYour Name 			center_freq.cfreq2 = agile_cfreq;
4716*5113495bSYour Name 		}
4717*5113495bSYour Name 
4718*5113495bSYour Name 		status = target_if_is_agile_span_overlap_with_operating_span
4719*5113495bSYour Name 				(spectral, ch_width,
4720*5113495bSYour Name 				 &center_freq, &is_overlapping);
4721*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status))
4722*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
4723*5113495bSYour Name 
4724*5113495bSYour Name 		if (is_overlapping) {
4725*5113495bSYour Name 			spectral_err("Agile freq %u, %u overlaps with operating span",
4726*5113495bSYour Name 				     center_freq.cfreq1, center_freq.cfreq2);
4727*5113495bSYour Name 			*err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
4728*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
4729*5113495bSYour Name 		}
4730*5113495bSYour Name 
4731*5113495bSYour Name 		if (ch_width[smode] == CH_WIDTH_80P80MHZ) {
4732*5113495bSYour Name 			bool is_valid_80p80;
4733*5113495bSYour Name 
4734*5113495bSYour Name 			status = target_if_spectral_is_valid_80p80_freq(
4735*5113495bSYour Name 						spectral->pdev_obj,
4736*5113495bSYour Name 						center_freq.cfreq1,
4737*5113495bSYour Name 						center_freq.cfreq2,
4738*5113495bSYour Name 						&is_valid_80p80);
4739*5113495bSYour Name 
4740*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(status))
4741*5113495bSYour Name 				return status;
4742*5113495bSYour Name 
4743*5113495bSYour Name 			if (!is_valid_80p80) {
4744*5113495bSYour Name 				spectral_err("Agile freq %u, %u is invalid 80+80 combination",
4745*5113495bSYour Name 					     center_freq.cfreq1,
4746*5113495bSYour Name 					     center_freq.cfreq2);
4747*5113495bSYour Name 				*err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
4748*5113495bSYour Name 				return QDF_STATUS_E_FAILURE;
4749*5113495bSYour Name 			}
4750*5113495bSYour Name 		}
4751*5113495bSYour Name 
4752*5113495bSYour Name 		sparams->ss_frequency.cfreq1 = center_freq.cfreq1;
4753*5113495bSYour Name 		sparams->ss_frequency.cfreq2 = center_freq.cfreq2;
4754*5113495bSYour Name 
4755*5113495bSYour Name 		break;
4756*5113495bSYour Name 
4757*5113495bSYour Name 	case SPECTRAL_PARAM_CHAN_WIDTH:
4758*5113495bSYour Name 		if (param->value >= CH_WIDTH_INVALID) {
4759*5113495bSYour Name 			spectral_err("invalid sscan width: %u", param->value);
4760*5113495bSYour Name 			*err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
4761*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
4762*5113495bSYour Name 		}
4763*5113495bSYour Name 
4764*5113495bSYour Name 		vdev = target_if_spectral_get_vdev(spectral, smode);
4765*5113495bSYour Name 		if (!vdev) {
4766*5113495bSYour Name 			spectral_err("vdev is null");
4767*5113495bSYour Name 			return QDF_STATUS_E_NULL_VALUE;
4768*5113495bSYour Name 		}
4769*5113495bSYour Name 		op_bw = target_if_vdev_get_ch_width(vdev);
4770*5113495bSYour Name 		wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
4771*5113495bSYour Name 
4772*5113495bSYour Name 		/* Validate the bandwidth */
4773*5113495bSYour Name 		status = target_if_is_sscan_bw_supported(
4774*5113495bSYour Name 				spectral, smode,
4775*5113495bSYour Name 				param->value, op_bw, &is_bw_supported,
4776*5113495bSYour Name 				spectral->params[SPECTRAL_SCAN_MODE_AGILE].
4777*5113495bSYour Name 				ss_frequency.cfreq2 > 0);
4778*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
4779*5113495bSYour Name 			spectral_err("Unable to check if given sscan_bw is supported");
4780*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
4781*5113495bSYour Name 		}
4782*5113495bSYour Name 
4783*5113495bSYour Name 		if (!is_bw_supported) {
4784*5113495bSYour Name 			spectral_err("sscan bw(%u) is not supported for the current operating width(%u) and sscan mode(%u)",
4785*5113495bSYour Name 				     param->value, op_bw, smode);
4786*5113495bSYour Name 			*err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
4787*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
4788*5113495bSYour Name 		}
4789*5113495bSYour Name 
4790*5113495bSYour Name 		sparams->ss_bandwidth = param->value;
4791*5113495bSYour Name 		spectral->sscan_width_configured[smode] = true;
4792*5113495bSYour Name 
4793*5113495bSYour Name 		break;
4794*5113495bSYour Name 	}
4795*5113495bSYour Name 
4796*5113495bSYour Name 	p_sops->configure_spectral(spectral, sparams, smode);
4797*5113495bSYour Name 	/* only to validate the writes */
4798*5113495bSYour Name 	p_sops->get_spectral_config(spectral, &params, smode);
4799*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
4800*5113495bSYour Name }
4801*5113495bSYour Name 
4802*5113495bSYour Name QDF_STATUS
target_if_set_spectral_config(struct wlan_objmgr_pdev * pdev,const struct spectral_cp_param * param,const enum spectral_scan_mode smode,enum spectral_cp_error_code * err)4803*5113495bSYour Name target_if_set_spectral_config(struct wlan_objmgr_pdev *pdev,
4804*5113495bSYour Name 			      const struct spectral_cp_param *param,
4805*5113495bSYour Name 			      const enum spectral_scan_mode smode,
4806*5113495bSYour Name 			      enum spectral_cp_error_code *err)
4807*5113495bSYour Name {
4808*5113495bSYour Name 	enum spectral_scan_mode mode = SPECTRAL_SCAN_MODE_NORMAL;
4809*5113495bSYour Name 	struct target_if_spectral *spectral;
4810*5113495bSYour Name 	QDF_STATUS status;
4811*5113495bSYour Name 
4812*5113495bSYour Name 	if (!err) {
4813*5113495bSYour Name 		spectral_err("Error code argument is null");
4814*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
4815*5113495bSYour Name 	}
4816*5113495bSYour Name 	*err = SPECTRAL_SCAN_ERR_INVALID;
4817*5113495bSYour Name 
4818*5113495bSYour Name 	if (!pdev) {
4819*5113495bSYour Name 		spectral_err("pdev object is NULL");
4820*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4821*5113495bSYour Name 	}
4822*5113495bSYour Name 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
4823*5113495bSYour Name 	if (!spectral) {
4824*5113495bSYour Name 		spectral_err("spectral object is NULL");
4825*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4826*5113495bSYour Name 	}
4827*5113495bSYour Name 
4828*5113495bSYour Name 	if (!param) {
4829*5113495bSYour Name 		spectral_err("parameter object is NULL");
4830*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4831*5113495bSYour Name 	}
4832*5113495bSYour Name 
4833*5113495bSYour Name 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
4834*5113495bSYour Name 		spectral_err("Invalid Spectral mode %u", smode);
4835*5113495bSYour Name 		*err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED;
4836*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4837*5113495bSYour Name 	}
4838*5113495bSYour Name 
4839*5113495bSYour Name 	if (!spectral->properties[smode][param->id].supported) {
4840*5113495bSYour Name 		spectral_err("Spectral parameter(%u) unsupported for mode %u",
4841*5113495bSYour Name 			     param->id, smode);
4842*5113495bSYour Name 		*err = SPECTRAL_SCAN_ERR_PARAM_UNSUPPORTED;
4843*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4844*5113495bSYour Name 	}
4845*5113495bSYour Name 
4846*5113495bSYour Name 	if (spectral->properties[smode][param->id].common_all_modes) {
4847*5113495bSYour Name 		spectral_warn("Setting Spectral parameter %u for all modes",
4848*5113495bSYour Name 			      param->id);
4849*5113495bSYour Name 		for (; mode < SPECTRAL_SCAN_MODE_MAX; mode++) {
4850*5113495bSYour Name 			status = _target_if_set_spectral_config
4851*5113495bSYour Name 						(spectral, param, mode, err);
4852*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(status))
4853*5113495bSYour Name 				return QDF_STATUS_E_FAILURE;
4854*5113495bSYour Name 		}
4855*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
4856*5113495bSYour Name 	}
4857*5113495bSYour Name 
4858*5113495bSYour Name 	return _target_if_set_spectral_config(spectral, param, smode, err);
4859*5113495bSYour Name }
4860*5113495bSYour Name 
4861*5113495bSYour Name /**
4862*5113495bSYour Name  * target_if_get_fft_bin_count() - Get fft bin count for a given fft length
4863*5113495bSYour Name  * @fft_len: FFT length
4864*5113495bSYour Name  *
4865*5113495bSYour Name  * API to get fft bin count for a given fft length
4866*5113495bSYour Name  *
4867*5113495bSYour Name  * Return: FFt bin count
4868*5113495bSYour Name  */
4869*5113495bSYour Name static int
target_if_get_fft_bin_count(int fft_len)4870*5113495bSYour Name target_if_get_fft_bin_count(int fft_len)
4871*5113495bSYour Name {
4872*5113495bSYour Name 	int bin_count = 0;
4873*5113495bSYour Name 
4874*5113495bSYour Name 	switch (fft_len) {
4875*5113495bSYour Name 	case 5:
4876*5113495bSYour Name 		bin_count = 16;
4877*5113495bSYour Name 		break;
4878*5113495bSYour Name 	case 6:
4879*5113495bSYour Name 		bin_count = 32;
4880*5113495bSYour Name 		break;
4881*5113495bSYour Name 	case 7:
4882*5113495bSYour Name 		bin_count = 64;
4883*5113495bSYour Name 		break;
4884*5113495bSYour Name 	case 8:
4885*5113495bSYour Name 		bin_count = 128;
4886*5113495bSYour Name 		break;
4887*5113495bSYour Name 	case 9:
4888*5113495bSYour Name 		bin_count = 256;
4889*5113495bSYour Name 		break;
4890*5113495bSYour Name 	default:
4891*5113495bSYour Name 		break;
4892*5113495bSYour Name 	}
4893*5113495bSYour Name 
4894*5113495bSYour Name 	return bin_count;
4895*5113495bSYour Name }
4896*5113495bSYour Name 
4897*5113495bSYour Name /**
4898*5113495bSYour Name  * target_if_init_upper_lower_flags() - Initializes control and extension
4899*5113495bSYour Name  * segment flags
4900*5113495bSYour Name  * @spectral: pointer to target if spectral object
4901*5113495bSYour Name  * @smode: Spectral scan mode
4902*5113495bSYour Name  *
4903*5113495bSYour Name  * API to initialize the control and extension flags with the lower/upper
4904*5113495bSYour Name  * segment based on the HT mode
4905*5113495bSYour Name  *
4906*5113495bSYour Name  * Return: FFt bin count
4907*5113495bSYour Name  */
4908*5113495bSYour Name static void
target_if_init_upper_lower_flags(struct target_if_spectral * spectral,enum spectral_scan_mode smode)4909*5113495bSYour Name target_if_init_upper_lower_flags(struct target_if_spectral *spectral,
4910*5113495bSYour Name 				 enum spectral_scan_mode smode)
4911*5113495bSYour Name {
4912*5113495bSYour Name 	int current_channel = 0;
4913*5113495bSYour Name 	int ext_channel = 0;
4914*5113495bSYour Name 	struct target_if_spectral_ops *p_sops =
4915*5113495bSYour Name 		GET_TARGET_IF_SPECTRAL_OPS(spectral);
4916*5113495bSYour Name 
4917*5113495bSYour Name 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
4918*5113495bSYour Name 		spectral_err("Invalid Spectral mode %u", smode);
4919*5113495bSYour Name 		return;
4920*5113495bSYour Name 	}
4921*5113495bSYour Name 	current_channel = p_sops->get_current_channel(spectral, smode);
4922*5113495bSYour Name 	ext_channel = p_sops->get_extension_channel(spectral, smode);
4923*5113495bSYour Name 
4924*5113495bSYour Name 	if ((current_channel == 0) || (ext_channel == 0))
4925*5113495bSYour Name 		return;
4926*5113495bSYour Name 
4927*5113495bSYour Name 	if (spectral->sc_spectral_20_40_mode) {
4928*5113495bSYour Name 		/* HT40 mode */
4929*5113495bSYour Name 		if (ext_channel < current_channel) {
4930*5113495bSYour Name 			spectral->lower_is_extension = 1;
4931*5113495bSYour Name 			spectral->upper_is_control = 1;
4932*5113495bSYour Name 			spectral->lower_is_control = 0;
4933*5113495bSYour Name 			spectral->upper_is_extension = 0;
4934*5113495bSYour Name 		} else {
4935*5113495bSYour Name 			spectral->lower_is_extension = 0;
4936*5113495bSYour Name 			spectral->upper_is_control = 0;
4937*5113495bSYour Name 			spectral->lower_is_control = 1;
4938*5113495bSYour Name 			spectral->upper_is_extension = 1;
4939*5113495bSYour Name 		}
4940*5113495bSYour Name 	} else {
4941*5113495bSYour Name 		/* HT20 mode, lower is always control */
4942*5113495bSYour Name 		spectral->lower_is_extension = 0;
4943*5113495bSYour Name 		spectral->upper_is_control = 0;
4944*5113495bSYour Name 		spectral->lower_is_control = 1;
4945*5113495bSYour Name 		spectral->upper_is_extension = 0;
4946*5113495bSYour Name 	}
4947*5113495bSYour Name }
4948*5113495bSYour Name 
4949*5113495bSYour Name /**
4950*5113495bSYour Name  * target_if_get_spectral_config() - Get spectral configuration
4951*5113495bSYour Name  * @pdev: Pointer to pdev object
4952*5113495bSYour Name  * @param: Pointer to spectral_config structure in which the configuration
4953*5113495bSYour Name  * should be returned
4954*5113495bSYour Name  * @smode: Spectral scan mode
4955*5113495bSYour Name  *
4956*5113495bSYour Name  * API to get the current spectral configuration
4957*5113495bSYour Name  *
4958*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
4959*5113495bSYour Name  */
4960*5113495bSYour Name QDF_STATUS
target_if_get_spectral_config(struct wlan_objmgr_pdev * pdev,struct spectral_config * param,enum spectral_scan_mode smode)4961*5113495bSYour Name target_if_get_spectral_config(struct wlan_objmgr_pdev *pdev,
4962*5113495bSYour Name 			      struct spectral_config *param,
4963*5113495bSYour Name 			      enum spectral_scan_mode smode)
4964*5113495bSYour Name {
4965*5113495bSYour Name 	struct target_if_spectral_ops *p_sops = NULL;
4966*5113495bSYour Name 	struct target_if_spectral *spectral = NULL;
4967*5113495bSYour Name 
4968*5113495bSYour Name 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
4969*5113495bSYour Name 
4970*5113495bSYour Name 	if (!spectral) {
4971*5113495bSYour Name 		spectral_err("SPECTRAL : Module doesn't exist");
4972*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4973*5113495bSYour Name 	}
4974*5113495bSYour Name 
4975*5113495bSYour Name 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
4976*5113495bSYour Name 
4977*5113495bSYour Name 	if (!p_sops) {
4978*5113495bSYour Name 		spectral_err("p_sops is null");
4979*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4980*5113495bSYour Name 	}
4981*5113495bSYour Name 
4982*5113495bSYour Name 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
4983*5113495bSYour Name 		spectral_err("Invalid Spectral mode %u", smode);
4984*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4985*5113495bSYour Name 	}
4986*5113495bSYour Name 
4987*5113495bSYour Name 	qdf_mem_zero(param, sizeof(struct spectral_config));
4988*5113495bSYour Name 	p_sops->get_spectral_config(spectral, param, smode);
4989*5113495bSYour Name 
4990*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
4991*5113495bSYour Name }
4992*5113495bSYour Name 
4993*5113495bSYour Name #ifdef WLAN_FEATURE_11BE
4994*5113495bSYour Name /**
4995*5113495bSYour Name  * target_if_spectral_get_num_detectors_for_higher_bws() - Get number of
4996*5113495bSYour Name  * Spectral detectors for higher bandwidths
4997*5113495bSYour Name  * @spectral: Pointer to target if Spectral object
4998*5113495bSYour Name  * @ch_width: channel width
4999*5113495bSYour Name  * @num_detectors: Pointer to the variable to store number of Spectral detectors
5000*5113495bSYour Name  *
5001*5113495bSYour Name  * API to get number of Spectral detectors used for scan in the given channel
5002*5113495bSYour Name  * width.
5003*5113495bSYour Name  *
5004*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_INVAL on failure
5005*5113495bSYour Name  */
5006*5113495bSYour Name static QDF_STATUS
target_if_spectral_get_num_detectors_for_higher_bws(struct target_if_spectral * spectral,enum phy_ch_width ch_width,uint32_t * num_detectors)5007*5113495bSYour Name target_if_spectral_get_num_detectors_for_higher_bws(
5008*5113495bSYour Name 				struct target_if_spectral *spectral,
5009*5113495bSYour Name 				enum phy_ch_width ch_width,
5010*5113495bSYour Name 				uint32_t *num_detectors)
5011*5113495bSYour Name {
5012*5113495bSYour Name 	switch (ch_width) {
5013*5113495bSYour Name 	case CH_WIDTH_320MHZ:
5014*5113495bSYour Name 		*num_detectors = spectral->capability.num_detectors_320mhz;
5015*5113495bSYour Name 		break;
5016*5113495bSYour Name 
5017*5113495bSYour Name 	default:
5018*5113495bSYour Name 		spectral_err("Unsupported channel width %d", ch_width);
5019*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
5020*5113495bSYour Name 	}
5021*5113495bSYour Name 
5022*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
5023*5113495bSYour Name }
5024*5113495bSYour Name #else
5025*5113495bSYour Name static QDF_STATUS
target_if_spectral_get_num_detectors_for_higher_bws(struct target_if_spectral * spectral,enum phy_ch_width ch_width,uint32_t * num_detectors)5026*5113495bSYour Name target_if_spectral_get_num_detectors_for_higher_bws(
5027*5113495bSYour Name 				struct target_if_spectral *spectral,
5028*5113495bSYour Name 				enum phy_ch_width ch_width,
5029*5113495bSYour Name 				uint32_t *num_detectors)
5030*5113495bSYour Name {
5031*5113495bSYour Name 	spectral_err("Unsupported channel width %d", ch_width);
5032*5113495bSYour Name 	return QDF_STATUS_E_INVAL;
5033*5113495bSYour Name }
5034*5113495bSYour Name #endif
5035*5113495bSYour Name 
5036*5113495bSYour Name /**
5037*5113495bSYour Name  * target_if_spectral_get_num_detectors() - Get number of Spectral detectors
5038*5113495bSYour Name  * @spectral: Pointer to target if Spectral object
5039*5113495bSYour Name  * @ch_width: channel width
5040*5113495bSYour Name  * @num_detectors: Pointer to the variable to store number of Spectral detectors
5041*5113495bSYour Name  *
5042*5113495bSYour Name  * API to get number of Spectral detectors used for scan in the given channel
5043*5113495bSYour Name  * width.
5044*5113495bSYour Name  *
5045*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_INVAL on failure
5046*5113495bSYour Name  */
5047*5113495bSYour Name static QDF_STATUS
target_if_spectral_get_num_detectors(struct target_if_spectral * spectral,enum phy_ch_width ch_width,uint32_t * num_detectors)5048*5113495bSYour Name target_if_spectral_get_num_detectors(struct target_if_spectral *spectral,
5049*5113495bSYour Name 				     enum phy_ch_width ch_width,
5050*5113495bSYour Name 				     uint32_t *num_detectors)
5051*5113495bSYour Name {
5052*5113495bSYour Name 	if (!spectral) {
5053*5113495bSYour Name 		spectral_err("target if spectral object is null");
5054*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
5055*5113495bSYour Name 	}
5056*5113495bSYour Name 
5057*5113495bSYour Name 	if (ch_width >= CH_WIDTH_INVALID) {
5058*5113495bSYour Name 		spectral_err("Invalid channel width %d", ch_width);
5059*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
5060*5113495bSYour Name 	}
5061*5113495bSYour Name 
5062*5113495bSYour Name 	if (!num_detectors) {
5063*5113495bSYour Name 		spectral_err("Invalid argument, number of detectors");
5064*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
5065*5113495bSYour Name 	}
5066*5113495bSYour Name 
5067*5113495bSYour Name 	switch (ch_width) {
5068*5113495bSYour Name 	case CH_WIDTH_20MHZ:
5069*5113495bSYour Name 		*num_detectors = spectral->capability.num_detectors_20mhz;
5070*5113495bSYour Name 		break;
5071*5113495bSYour Name 
5072*5113495bSYour Name 	case CH_WIDTH_40MHZ:
5073*5113495bSYour Name 		*num_detectors = spectral->capability.num_detectors_40mhz;
5074*5113495bSYour Name 		break;
5075*5113495bSYour Name 
5076*5113495bSYour Name 	case CH_WIDTH_80MHZ:
5077*5113495bSYour Name 		*num_detectors = spectral->capability.num_detectors_80mhz;
5078*5113495bSYour Name 		break;
5079*5113495bSYour Name 
5080*5113495bSYour Name 	case CH_WIDTH_160MHZ:
5081*5113495bSYour Name 		*num_detectors = spectral->capability.num_detectors_160mhz;
5082*5113495bSYour Name 		break;
5083*5113495bSYour Name 
5084*5113495bSYour Name 	case CH_WIDTH_80P80MHZ:
5085*5113495bSYour Name 		*num_detectors = spectral->capability.num_detectors_80p80mhz;
5086*5113495bSYour Name 		break;
5087*5113495bSYour Name 
5088*5113495bSYour Name 	default:
5089*5113495bSYour Name 		return target_if_spectral_get_num_detectors_for_higher_bws(
5090*5113495bSYour Name 			spectral, ch_width, num_detectors);
5091*5113495bSYour Name 	}
5092*5113495bSYour Name 
5093*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
5094*5113495bSYour Name }
5095*5113495bSYour Name 
5096*5113495bSYour Name /**
5097*5113495bSYour Name  * target_if_spectral_finite_scan_init() - Initializations required for finite
5098*5113495bSYour Name  * Spectral scan
5099*5113495bSYour Name  * @spectral: Pointer to target of Spctral object
5100*5113495bSYour Name  * @smode: Spectral scan mode
5101*5113495bSYour Name  *
5102*5113495bSYour Name  * This routine initializes the finite Spectral scan. Finite Spectral scan is
5103*5113495bSYour Name  * triggered by configuring a non zero scan count.
5104*5113495bSYour Name  *
5105*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS on success
5106*5113495bSYour Name  */
5107*5113495bSYour Name static QDF_STATUS
target_if_spectral_finite_scan_init(struct target_if_spectral * spectral,enum spectral_scan_mode smode)5108*5113495bSYour Name target_if_spectral_finite_scan_init(struct target_if_spectral *spectral,
5109*5113495bSYour Name 				    enum spectral_scan_mode smode)
5110*5113495bSYour Name {
5111*5113495bSYour Name 	struct target_if_finite_spectral_scan_params *finite_scan;
5112*5113495bSYour Name 	enum phy_ch_width ch_width;
5113*5113495bSYour Name 	uint32_t num_detectors;
5114*5113495bSYour Name 	QDF_STATUS status;
5115*5113495bSYour Name 	uint16_t sscan_count;
5116*5113495bSYour Name 
5117*5113495bSYour Name 	if (!spectral) {
5118*5113495bSYour Name 		spectral_err("target if spectral object is null");
5119*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
5120*5113495bSYour Name 	}
5121*5113495bSYour Name 
5122*5113495bSYour Name 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
5123*5113495bSYour Name 		spectral_err("Invalid Spectral mode");
5124*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
5125*5113495bSYour Name 	}
5126*5113495bSYour Name 
5127*5113495bSYour Name 	ch_width = spectral->ch_width[smode];
5128*5113495bSYour Name 	status = target_if_spectral_get_num_detectors(spectral, ch_width,
5129*5113495bSYour Name 						      &num_detectors);
5130*5113495bSYour Name 
5131*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
5132*5113495bSYour Name 		spectral_err("Failed to get number of detectors");
5133*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
5134*5113495bSYour Name 	}
5135*5113495bSYour Name 
5136*5113495bSYour Name 	finite_scan = &spectral->finite_scan[smode];
5137*5113495bSYour Name 	sscan_count =  spectral->params[smode].ss_count;
5138*5113495bSYour Name 
5139*5113495bSYour Name 	finite_scan->finite_spectral_scan =  true;
5140*5113495bSYour Name 	finite_scan->num_reports_expected = num_detectors * sscan_count;
5141*5113495bSYour Name 
5142*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
5143*5113495bSYour Name }
5144*5113495bSYour Name 
5145*5113495bSYour Name /**
5146*5113495bSYour Name  * target_if_spectral_scan_enable_params() - Enable use of desired Spectral
5147*5113495bSYour Name  *                                           parameters
5148*5113495bSYour Name  * @spectral: Pointer to Spectral target_if internal private data
5149*5113495bSYour Name  * @spectral_params: Pointer to Spectral parameters
5150*5113495bSYour Name  * @smode: Spectral scan mode
5151*5113495bSYour Name  * @err: Spectral error code
5152*5113495bSYour Name  *
5153*5113495bSYour Name  * Enable use of desired Spectral parameters by configuring them into HW, and
5154*5113495bSYour Name  * starting Spectral scan
5155*5113495bSYour Name  *
5156*5113495bSYour Name  * Return: 0 on success, 1 on failure
5157*5113495bSYour Name  */
5158*5113495bSYour Name int
target_if_spectral_scan_enable_params(struct target_if_spectral * spectral,struct spectral_config * spectral_params,enum spectral_scan_mode smode,enum spectral_cp_error_code * err)5159*5113495bSYour Name target_if_spectral_scan_enable_params(struct target_if_spectral *spectral,
5160*5113495bSYour Name 				      struct spectral_config *spectral_params,
5161*5113495bSYour Name 				      enum spectral_scan_mode smode,
5162*5113495bSYour Name 				      enum spectral_cp_error_code *err)
5163*5113495bSYour Name {
5164*5113495bSYour Name 	int extension_channel = 0;
5165*5113495bSYour Name 	int current_channel = 0;
5166*5113495bSYour Name 	struct target_if_spectral_ops *p_sops = NULL;
5167*5113495bSYour Name 	QDF_STATUS status;
5168*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev;
5169*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
5170*5113495bSYour Name 
5171*5113495bSYour Name 	if (!spectral) {
5172*5113495bSYour Name 		spectral_err("Spectral LMAC object is NULL");
5173*5113495bSYour Name 		return 1;
5174*5113495bSYour Name 	}
5175*5113495bSYour Name 
5176*5113495bSYour Name 	pdev =  spectral->pdev_obj;
5177*5113495bSYour Name 	if (!pdev) {
5178*5113495bSYour Name 		spectral_err("pdev is null");
5179*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
5180*5113495bSYour Name 	}
5181*5113495bSYour Name 
5182*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
5183*5113495bSYour Name 	if (!psoc) {
5184*5113495bSYour Name 		spectral_err("psoc is null");
5185*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
5186*5113495bSYour Name 	}
5187*5113495bSYour Name 
5188*5113495bSYour Name 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
5189*5113495bSYour Name 		spectral_err("Invalid Spectral mode %u", smode);
5190*5113495bSYour Name 		return 1;
5191*5113495bSYour Name 	}
5192*5113495bSYour Name 
5193*5113495bSYour Name 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
5194*5113495bSYour Name 
5195*5113495bSYour Name 	if (!p_sops) {
5196*5113495bSYour Name 		spectral_err("p_sops is NULL");
5197*5113495bSYour Name 		return 1;
5198*5113495bSYour Name 	}
5199*5113495bSYour Name 
5200*5113495bSYour Name 	spectral->sc_spectral_noise_pwr_cal =
5201*5113495bSYour Name 	    spectral_params->ss_spectral_pri ? 1 : 0;
5202*5113495bSYour Name 
5203*5113495bSYour Name 	/* check if extension channel is present */
5204*5113495bSYour Name 	extension_channel = p_sops->get_extension_channel(spectral, smode);
5205*5113495bSYour Name 	current_channel = p_sops->get_current_channel(spectral, smode);
5206*5113495bSYour Name 
5207*5113495bSYour Name 	if (spectral->capability.advncd_spectral_cap) {
5208*5113495bSYour Name 		spectral->lb_edge_extrabins = 0;
5209*5113495bSYour Name 		spectral->rb_edge_extrabins = 0;
5210*5113495bSYour Name 
5211*5113495bSYour Name 		if (spectral->is_lb_edge_extrabins_format &&
5212*5113495bSYour Name 		    spectral->params[smode].ss_rpt_mode == 2) {
5213*5113495bSYour Name 			spectral->lb_edge_extrabins = 4;
5214*5113495bSYour Name 		}
5215*5113495bSYour Name 
5216*5113495bSYour Name 		if (spectral->is_rb_edge_extrabins_format &&
5217*5113495bSYour Name 		    spectral->params[smode].ss_rpt_mode == 2) {
5218*5113495bSYour Name 			spectral->rb_edge_extrabins = 4;
5219*5113495bSYour Name 		}
5220*5113495bSYour Name 
5221*5113495bSYour Name 		if (spectral->ch_width[smode] == CH_WIDTH_20MHZ) {
5222*5113495bSYour Name 			spectral->sc_spectral_20_40_mode = 0;
5223*5113495bSYour Name 
5224*5113495bSYour Name 			spectral->spectral_numbins =
5225*5113495bSYour Name 			    target_if_get_fft_bin_count(
5226*5113495bSYour Name 				spectral->params[smode].ss_fft_size);
5227*5113495bSYour Name 			spectral->spectral_fft_len =
5228*5113495bSYour Name 			    target_if_get_fft_bin_count(
5229*5113495bSYour Name 				spectral->params[smode].ss_fft_size);
5230*5113495bSYour Name 			spectral->spectral_data_len =
5231*5113495bSYour Name 			    target_if_get_fft_bin_count(
5232*5113495bSYour Name 				spectral->params[smode].ss_fft_size);
5233*5113495bSYour Name 			/*
5234*5113495bSYour Name 			 * Initialize classifier params to be sent to user
5235*5113495bSYour Name 			 * space classifier
5236*5113495bSYour Name 			 */
5237*5113495bSYour Name 			spectral->classifier_params.lower_chan_in_mhz =
5238*5113495bSYour Name 			    current_channel;
5239*5113495bSYour Name 			spectral->classifier_params.upper_chan_in_mhz = 0;
5240*5113495bSYour Name 
5241*5113495bSYour Name 		} else if (spectral->ch_width[smode] == CH_WIDTH_40MHZ) {
5242*5113495bSYour Name 			/* TODO : Remove this variable */
5243*5113495bSYour Name 			spectral->sc_spectral_20_40_mode = 1;
5244*5113495bSYour Name 			spectral->spectral_numbins =
5245*5113495bSYour Name 			    target_if_get_fft_bin_count(
5246*5113495bSYour Name 				spectral->params[smode].ss_fft_size);
5247*5113495bSYour Name 			spectral->spectral_fft_len =
5248*5113495bSYour Name 			    target_if_get_fft_bin_count(
5249*5113495bSYour Name 				spectral->params[smode].ss_fft_size);
5250*5113495bSYour Name 			spectral->spectral_data_len =
5251*5113495bSYour Name 			    target_if_get_fft_bin_count(
5252*5113495bSYour Name 				spectral->params[smode].ss_fft_size);
5253*5113495bSYour Name 
5254*5113495bSYour Name 			/*
5255*5113495bSYour Name 			 * Initialize classifier params to be sent to user
5256*5113495bSYour Name 			 * space classifier
5257*5113495bSYour Name 			 */
5258*5113495bSYour Name 			if (extension_channel < current_channel) {
5259*5113495bSYour Name 				spectral->classifier_params.lower_chan_in_mhz =
5260*5113495bSYour Name 				    extension_channel;
5261*5113495bSYour Name 				spectral->classifier_params.upper_chan_in_mhz =
5262*5113495bSYour Name 				    current_channel;
5263*5113495bSYour Name 			} else {
5264*5113495bSYour Name 				spectral->classifier_params.lower_chan_in_mhz =
5265*5113495bSYour Name 				    current_channel;
5266*5113495bSYour Name 				spectral->classifier_params.upper_chan_in_mhz =
5267*5113495bSYour Name 				    extension_channel;
5268*5113495bSYour Name 			}
5269*5113495bSYour Name 
5270*5113495bSYour Name 		} else if (spectral->ch_width[smode] == CH_WIDTH_80MHZ) {
5271*5113495bSYour Name 			/* Set the FFT Size */
5272*5113495bSYour Name 			/* TODO : Remove this variable */
5273*5113495bSYour Name 			spectral->sc_spectral_20_40_mode = 0;
5274*5113495bSYour Name 			spectral->spectral_numbins =
5275*5113495bSYour Name 			    target_if_get_fft_bin_count(
5276*5113495bSYour Name 				spectral->params[smode].ss_fft_size);
5277*5113495bSYour Name 			spectral->spectral_fft_len =
5278*5113495bSYour Name 			    target_if_get_fft_bin_count(
5279*5113495bSYour Name 				spectral->params[smode].ss_fft_size);
5280*5113495bSYour Name 			spectral->spectral_data_len =
5281*5113495bSYour Name 			    target_if_get_fft_bin_count(
5282*5113495bSYour Name 				spectral->params[smode].ss_fft_size);
5283*5113495bSYour Name 
5284*5113495bSYour Name 			/*
5285*5113495bSYour Name 			 * Initialize classifier params to be sent to user
5286*5113495bSYour Name 			 * space classifier
5287*5113495bSYour Name 			 */
5288*5113495bSYour Name 			spectral->classifier_params.lower_chan_in_mhz =
5289*5113495bSYour Name 			    current_channel;
5290*5113495bSYour Name 			spectral->classifier_params.upper_chan_in_mhz = 0;
5291*5113495bSYour Name 
5292*5113495bSYour Name 			/*
5293*5113495bSYour Name 			 * Initialize classifier params to be sent to user
5294*5113495bSYour Name 			 * space classifier
5295*5113495bSYour Name 			 */
5296*5113495bSYour Name 			if (extension_channel < current_channel) {
5297*5113495bSYour Name 				spectral->classifier_params.lower_chan_in_mhz =
5298*5113495bSYour Name 				    extension_channel;
5299*5113495bSYour Name 				spectral->classifier_params.upper_chan_in_mhz =
5300*5113495bSYour Name 				    current_channel;
5301*5113495bSYour Name 			} else {
5302*5113495bSYour Name 				spectral->classifier_params.lower_chan_in_mhz =
5303*5113495bSYour Name 				    current_channel;
5304*5113495bSYour Name 				spectral->classifier_params.upper_chan_in_mhz =
5305*5113495bSYour Name 				    extension_channel;
5306*5113495bSYour Name 			}
5307*5113495bSYour Name 
5308*5113495bSYour Name 		} else if (is_ch_width_160_or_80p80(
5309*5113495bSYour Name 			   spectral->ch_width[smode])) {
5310*5113495bSYour Name 			/* Set the FFT Size */
5311*5113495bSYour Name 
5312*5113495bSYour Name 			/* The below applies to both 160 and 80+80 cases */
5313*5113495bSYour Name 
5314*5113495bSYour Name 			/* TODO : Remove this variable */
5315*5113495bSYour Name 			spectral->sc_spectral_20_40_mode = 0;
5316*5113495bSYour Name 			spectral->spectral_numbins =
5317*5113495bSYour Name 			    target_if_get_fft_bin_count(
5318*5113495bSYour Name 				spectral->params[smode].ss_fft_size);
5319*5113495bSYour Name 			spectral->spectral_fft_len =
5320*5113495bSYour Name 			    target_if_get_fft_bin_count(
5321*5113495bSYour Name 				spectral->params[smode].ss_fft_size);
5322*5113495bSYour Name 			spectral->spectral_data_len =
5323*5113495bSYour Name 			    target_if_get_fft_bin_count(
5324*5113495bSYour Name 				spectral->params[smode].ss_fft_size);
5325*5113495bSYour Name 
5326*5113495bSYour Name 			/*
5327*5113495bSYour Name 			 * Initialize classifier params to be sent to user
5328*5113495bSYour Name 			 * space classifier
5329*5113495bSYour Name 			 */
5330*5113495bSYour Name 			spectral->classifier_params.lower_chan_in_mhz =
5331*5113495bSYour Name 			    current_channel;
5332*5113495bSYour Name 			spectral->classifier_params.upper_chan_in_mhz = 0;
5333*5113495bSYour Name 
5334*5113495bSYour Name 			/*
5335*5113495bSYour Name 			 * Initialize classifier params to be sent to user
5336*5113495bSYour Name 			 * space classifier
5337*5113495bSYour Name 			 */
5338*5113495bSYour Name 			if (extension_channel < current_channel) {
5339*5113495bSYour Name 				spectral->classifier_params.lower_chan_in_mhz =
5340*5113495bSYour Name 				    extension_channel;
5341*5113495bSYour Name 				spectral->classifier_params.upper_chan_in_mhz =
5342*5113495bSYour Name 				    current_channel;
5343*5113495bSYour Name 			} else {
5344*5113495bSYour Name 				spectral->classifier_params.lower_chan_in_mhz =
5345*5113495bSYour Name 				    current_channel;
5346*5113495bSYour Name 				spectral->classifier_params.upper_chan_in_mhz =
5347*5113495bSYour Name 				    extension_channel;
5348*5113495bSYour Name 			}
5349*5113495bSYour Name 		}
5350*5113495bSYour Name 
5351*5113495bSYour Name 		if (spectral->spectral_numbins) {
5352*5113495bSYour Name 			spectral->spectral_numbins +=
5353*5113495bSYour Name 			    spectral->lb_edge_extrabins;
5354*5113495bSYour Name 			spectral->spectral_numbins +=
5355*5113495bSYour Name 			    spectral->rb_edge_extrabins;
5356*5113495bSYour Name 		}
5357*5113495bSYour Name 
5358*5113495bSYour Name 		if (spectral->spectral_fft_len) {
5359*5113495bSYour Name 			spectral->spectral_fft_len +=
5360*5113495bSYour Name 			    spectral->lb_edge_extrabins;
5361*5113495bSYour Name 			spectral->spectral_fft_len +=
5362*5113495bSYour Name 			    spectral->rb_edge_extrabins;
5363*5113495bSYour Name 		}
5364*5113495bSYour Name 
5365*5113495bSYour Name 		if (spectral->spectral_data_len) {
5366*5113495bSYour Name 			spectral->spectral_data_len +=
5367*5113495bSYour Name 			    spectral->lb_edge_extrabins;
5368*5113495bSYour Name 			spectral->spectral_data_len +=
5369*5113495bSYour Name 			    spectral->rb_edge_extrabins;
5370*5113495bSYour Name 		}
5371*5113495bSYour Name 	} else {
5372*5113495bSYour Name 		/*
5373*5113495bSYour Name 		 * The decision to find 20/40 mode is found based on the
5374*5113495bSYour Name 		 * presence of extension channel
5375*5113495bSYour Name 		 * instead of channel width, as the channel width can
5376*5113495bSYour Name 		 * dynamically change
5377*5113495bSYour Name 		 */
5378*5113495bSYour Name 
5379*5113495bSYour Name 		if (extension_channel == 0) {
5380*5113495bSYour Name 			spectral->spectral_numbins = SPECTRAL_HT20_NUM_BINS;
5381*5113495bSYour Name 			spectral->spectral_dc_index = SPECTRAL_HT20_DC_INDEX;
5382*5113495bSYour Name 			spectral->spectral_fft_len = SPECTRAL_HT20_FFT_LEN;
5383*5113495bSYour Name 			spectral->spectral_data_len =
5384*5113495bSYour Name 			    SPECTRAL_HT20_TOTAL_DATA_LEN;
5385*5113495bSYour Name 			/* only valid in 20-40 mode */
5386*5113495bSYour Name 			spectral->spectral_lower_max_index_offset = -1;
5387*5113495bSYour Name 			/* only valid in 20-40 mode */
5388*5113495bSYour Name 			spectral->spectral_upper_max_index_offset = -1;
5389*5113495bSYour Name 			spectral->spectral_max_index_offset =
5390*5113495bSYour Name 			    spectral->spectral_fft_len + 2;
5391*5113495bSYour Name 			spectral->sc_spectral_20_40_mode = 0;
5392*5113495bSYour Name 
5393*5113495bSYour Name 			/*
5394*5113495bSYour Name 			 * Initialize classifier params to be sent to user
5395*5113495bSYour Name 			 * space classifier
5396*5113495bSYour Name 			 */
5397*5113495bSYour Name 			spectral->classifier_params.lower_chan_in_mhz =
5398*5113495bSYour Name 			    current_channel;
5399*5113495bSYour Name 			spectral->classifier_params.upper_chan_in_mhz = 0;
5400*5113495bSYour Name 
5401*5113495bSYour Name 		} else {
5402*5113495bSYour Name 			spectral->spectral_numbins =
5403*5113495bSYour Name 			    SPECTRAL_HT40_TOTAL_NUM_BINS;
5404*5113495bSYour Name 			spectral->spectral_fft_len = SPECTRAL_HT40_FFT_LEN;
5405*5113495bSYour Name 			spectral->spectral_data_len =
5406*5113495bSYour Name 			    SPECTRAL_HT40_TOTAL_DATA_LEN;
5407*5113495bSYour Name 			spectral->spectral_dc_index = SPECTRAL_HT40_DC_INDEX;
5408*5113495bSYour Name 			/* only valid in 20 mode */
5409*5113495bSYour Name 			spectral->spectral_max_index_offset = -1;
5410*5113495bSYour Name 			spectral->spectral_lower_max_index_offset =
5411*5113495bSYour Name 			    spectral->spectral_fft_len + 2;
5412*5113495bSYour Name 			spectral->spectral_upper_max_index_offset =
5413*5113495bSYour Name 			    spectral->spectral_fft_len + 5;
5414*5113495bSYour Name 			spectral->sc_spectral_20_40_mode = 1;
5415*5113495bSYour Name 
5416*5113495bSYour Name 			/*
5417*5113495bSYour Name 			 * Initialize classifier params to be sent to user
5418*5113495bSYour Name 			 * space classifier
5419*5113495bSYour Name 			 */
5420*5113495bSYour Name 			if (extension_channel < current_channel) {
5421*5113495bSYour Name 				spectral->classifier_params.lower_chan_in_mhz =
5422*5113495bSYour Name 				    extension_channel;
5423*5113495bSYour Name 				spectral->classifier_params.upper_chan_in_mhz =
5424*5113495bSYour Name 				    current_channel;
5425*5113495bSYour Name 			} else {
5426*5113495bSYour Name 				spectral->classifier_params.lower_chan_in_mhz =
5427*5113495bSYour Name 				    current_channel;
5428*5113495bSYour Name 				spectral->classifier_params.upper_chan_in_mhz =
5429*5113495bSYour Name 				    extension_channel;
5430*5113495bSYour Name 			}
5431*5113495bSYour Name 		}
5432*5113495bSYour Name 	}
5433*5113495bSYour Name 
5434*5113495bSYour Name 	spectral->send_single_packet = 0;
5435*5113495bSYour Name 	spectral->classifier_params.spectral_20_40_mode =
5436*5113495bSYour Name 	    spectral->sc_spectral_20_40_mode;
5437*5113495bSYour Name 	spectral->classifier_params.spectral_dc_index =
5438*5113495bSYour Name 	    spectral->spectral_dc_index;
5439*5113495bSYour Name 	spectral->spectral_sent_msg = 0;
5440*5113495bSYour Name 	spectral->classify_scan = 0;
5441*5113495bSYour Name 	spectral->num_spectral_data = 0;
5442*5113495bSYour Name 
5443*5113495bSYour Name 	if (!p_sops->is_spectral_active(spectral, smode)) {
5444*5113495bSYour Name 		p_sops->configure_spectral(spectral, spectral_params, smode);
5445*5113495bSYour Name 		spectral->rparams.marker[smode].is_valid = false;
5446*5113495bSYour Name 
5447*5113495bSYour Name 		if (spectral->params[smode].ss_count) {
5448*5113495bSYour Name 			status = target_if_spectral_finite_scan_init(spectral,
5449*5113495bSYour Name 								     smode);
5450*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(status)) {
5451*5113495bSYour Name 				spectral_err("Failed to init finite scan");
5452*5113495bSYour Name 				return 1;
5453*5113495bSYour Name 			}
5454*5113495bSYour Name 		}
5455*5113495bSYour Name 		p_sops->start_spectral_scan(spectral, smode, err);
5456*5113495bSYour Name 		spectral->timestamp_war.timestamp_war_offset[smode] = 0;
5457*5113495bSYour Name 		spectral->timestamp_war.last_fft_timestamp[smode] = 0;
5458*5113495bSYour Name 	}
5459*5113495bSYour Name 
5460*5113495bSYour Name 	/* get current spectral configuration */
5461*5113495bSYour Name 	p_sops->get_spectral_config(spectral, &spectral->params[smode], smode);
5462*5113495bSYour Name 
5463*5113495bSYour Name 	target_if_init_upper_lower_flags(spectral, smode);
5464*5113495bSYour Name 
5465*5113495bSYour Name 	return 0;
5466*5113495bSYour Name }
5467*5113495bSYour Name 
5468*5113495bSYour Name /**
5469*5113495bSYour Name  * target_if_is_aspectral_prohibited_by_adfs() - Is Agile Spectral prohibited by
5470*5113495bSYour Name  * Agile DFS
5471*5113495bSYour Name  * @psoc: Pointer to psoc
5472*5113495bSYour Name  * @object: Pointer to pdev
5473*5113495bSYour Name  * @arg: Pointer to flag which indicates whether Agile Spectral is prohibited
5474*5113495bSYour Name  *
5475*5113495bSYour Name  * This API checks whether Agile DFS is running on any of the pdevs. If so, it
5476*5113495bSYour Name  * indicates that Agile Spectral scan is prohibited by Agile DFS.
5477*5113495bSYour Name  *
5478*5113495bSYour Name  * Return: void
5479*5113495bSYour Name  */
5480*5113495bSYour Name static void
target_if_is_aspectral_prohibited_by_adfs(struct wlan_objmgr_psoc * psoc,void * object,void * arg)5481*5113495bSYour Name target_if_is_aspectral_prohibited_by_adfs(struct wlan_objmgr_psoc *psoc,
5482*5113495bSYour Name 					  void *object, void *arg)
5483*5113495bSYour Name {
5484*5113495bSYour Name 	bool *is_aspectral_prohibited = arg;
5485*5113495bSYour Name 	struct wlan_objmgr_pdev *cur_pdev = object;
5486*5113495bSYour Name 	bool is_agile_precac_enabled_cur_pdev = false;
5487*5113495bSYour Name 	bool is_agile_rcac_enabled_cur_pdev = false;
5488*5113495bSYour Name 	QDF_STATUS status;
5489*5113495bSYour Name 
5490*5113495bSYour Name 	if (!is_aspectral_prohibited) {
5491*5113495bSYour Name 		spectral_err("Arg(Indication flag for agile spectral prohibition) is null.");
5492*5113495bSYour Name 		return;
5493*5113495bSYour Name 	}
5494*5113495bSYour Name 
5495*5113495bSYour Name 	if (*is_aspectral_prohibited)
5496*5113495bSYour Name 		return;
5497*5113495bSYour Name 
5498*5113495bSYour Name 	if (!psoc) {
5499*5113495bSYour Name 		spectral_err("psoc is null.");
5500*5113495bSYour Name 		*is_aspectral_prohibited = true;
5501*5113495bSYour Name 		return;
5502*5113495bSYour Name 	}
5503*5113495bSYour Name 
5504*5113495bSYour Name 	if (!cur_pdev) {
5505*5113495bSYour Name 		spectral_err("Current pdev is null.");
5506*5113495bSYour Name 		*is_aspectral_prohibited = true;
5507*5113495bSYour Name 		return;
5508*5113495bSYour Name 	}
5509*5113495bSYour Name 
5510*5113495bSYour Name 	status = ucfg_dfs_get_agile_precac_enable
5511*5113495bSYour Name 				(cur_pdev,
5512*5113495bSYour Name 				 &is_agile_precac_enabled_cur_pdev);
5513*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
5514*5113495bSYour Name 		spectral_err("Get agile precac failed, prohibiting aSpectral");
5515*5113495bSYour Name 		*is_aspectral_prohibited = true;
5516*5113495bSYour Name 		return;
5517*5113495bSYour Name 	}
5518*5113495bSYour Name 
5519*5113495bSYour Name 	status = ucfg_dfs_get_rcac_enable(cur_pdev,
5520*5113495bSYour Name 					  &is_agile_rcac_enabled_cur_pdev);
5521*5113495bSYour Name 
5522*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
5523*5113495bSYour Name 		spectral_err("Get agile RCAC failed, prohibiting aSpectral");
5524*5113495bSYour Name 		*is_aspectral_prohibited = true;
5525*5113495bSYour Name 		return;
5526*5113495bSYour Name 	}
5527*5113495bSYour Name 
5528*5113495bSYour Name 	if (is_agile_precac_enabled_cur_pdev) {
5529*5113495bSYour Name 		spectral_err("aDFS preCAC is in progress on one of the pdevs");
5530*5113495bSYour Name 		*is_aspectral_prohibited = true;
5531*5113495bSYour Name 	} else if (is_agile_rcac_enabled_cur_pdev) {
5532*5113495bSYour Name 		spectral_err("aDFS RCAC is in progress on one of the pdevs");
5533*5113495bSYour Name 		*is_aspectral_prohibited = true;
5534*5113495bSYour Name 	}
5535*5113495bSYour Name }
5536*5113495bSYour Name 
5537*5113495bSYour Name /**
5538*5113495bSYour Name  * target_if_get_curr_band() - Get current operating band of pdev
5539*5113495bSYour Name  * @pdev: pointer to pdev object
5540*5113495bSYour Name  * @vdev_id: id of vdev
5541*5113495bSYour Name  *
5542*5113495bSYour Name  * API to get current operating band of a given pdev.
5543*5113495bSYour Name  *
5544*5113495bSYour Name  * Return: if success enum reg_wifi_band, REG_BAND_UNKNOWN in case of failure
5545*5113495bSYour Name  */
5546*5113495bSYour Name static enum reg_wifi_band
target_if_get_curr_band(struct wlan_objmgr_pdev * pdev,uint8_t vdev_id)5547*5113495bSYour Name target_if_get_curr_band(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id)
5548*5113495bSYour Name {
5549*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
5550*5113495bSYour Name 	int16_t chan_freq;
5551*5113495bSYour Name 	enum reg_wifi_band cur_band;
5552*5113495bSYour Name 
5553*5113495bSYour Name 	if (!pdev) {
5554*5113495bSYour Name 		spectral_err("pdev is NULL");
5555*5113495bSYour Name 		return REG_BAND_UNKNOWN;
5556*5113495bSYour Name 	}
5557*5113495bSYour Name 
5558*5113495bSYour Name 	if (vdev_id == WLAN_INVALID_VDEV_ID)
5559*5113495bSYour Name 		vdev = wlan_objmgr_pdev_get_first_vdev(pdev, WLAN_SPECTRAL_ID);
5560*5113495bSYour Name 	else
5561*5113495bSYour Name 		vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id,
5562*5113495bSYour Name 							    WLAN_SPECTRAL_ID);
5563*5113495bSYour Name 	if (!vdev) {
5564*5113495bSYour Name 		spectral_debug("vdev is NULL");
5565*5113495bSYour Name 		return REG_BAND_UNKNOWN;
5566*5113495bSYour Name 	}
5567*5113495bSYour Name 	chan_freq = target_if_vdev_get_chan_freq(vdev);
5568*5113495bSYour Name 	cur_band = wlan_reg_freq_to_band(chan_freq);
5569*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
5570*5113495bSYour Name 
5571*5113495bSYour Name 	return cur_band;
5572*5113495bSYour Name }
5573*5113495bSYour Name 
5574*5113495bSYour Name /**
5575*5113495bSYour Name  * target_if_is_agile_scan_active_in_5g() - Is Agile Spectral scan active on
5576*5113495bSYour Name  * any of the 5G pdevs
5577*5113495bSYour Name  * @psoc: Pointer to psoc
5578*5113495bSYour Name  * @object: Pointer to pdev
5579*5113495bSYour Name  * @arg: Pointer to flag which indicates whether Agile Spectral scan is in
5580*5113495bSYour Name  *       progress in any 5G pdevs
5581*5113495bSYour Name  *
5582*5113495bSYour Name  * Return: void
5583*5113495bSYour Name  */
5584*5113495bSYour Name static void
target_if_is_agile_scan_active_in_5g(struct wlan_objmgr_psoc * psoc,void * object,void * arg)5585*5113495bSYour Name target_if_is_agile_scan_active_in_5g(struct wlan_objmgr_psoc *psoc,
5586*5113495bSYour Name 				     void *object, void *arg)
5587*5113495bSYour Name {
5588*5113495bSYour Name 	enum reg_wifi_band band;
5589*5113495bSYour Name 	bool *is_agile_scan_inprog_5g_pdev = arg;
5590*5113495bSYour Name 	struct target_if_spectral *spectral;
5591*5113495bSYour Name 	struct wlan_objmgr_pdev *cur_pdev = object;
5592*5113495bSYour Name 	struct target_if_spectral_ops *p_sops;
5593*5113495bSYour Name 
5594*5113495bSYour Name 	if (*is_agile_scan_inprog_5g_pdev)
5595*5113495bSYour Name 		return;
5596*5113495bSYour Name 
5597*5113495bSYour Name 	spectral = get_target_if_spectral_handle_from_pdev(cur_pdev);
5598*5113495bSYour Name 	if (!spectral) {
5599*5113495bSYour Name 		spectral_err("target if spectral handle is NULL");
5600*5113495bSYour Name 		return;
5601*5113495bSYour Name 	}
5602*5113495bSYour Name 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
5603*5113495bSYour Name 
5604*5113495bSYour Name 	band = target_if_get_curr_band(
5605*5113495bSYour Name 			cur_pdev, spectral->vdev_id[SPECTRAL_SCAN_MODE_AGILE]);
5606*5113495bSYour Name 	if (band == REG_BAND_UNKNOWN) {
5607*5113495bSYour Name 		spectral_debug("Failed to get current band");
5608*5113495bSYour Name 		return;
5609*5113495bSYour Name 	}
5610*5113495bSYour Name 
5611*5113495bSYour Name 	if (band == REG_BAND_5G &&
5612*5113495bSYour Name 	    p_sops->is_spectral_active(spectral, SPECTRAL_SCAN_MODE_AGILE))
5613*5113495bSYour Name 		*is_agile_scan_inprog_5g_pdev = true;
5614*5113495bSYour Name }
5615*5113495bSYour Name 
5616*5113495bSYour Name /**
5617*5113495bSYour Name  * target_if_is_agile_supported_cur_chmask() - Is Agile Spectral scan supported
5618*5113495bSYour Name  * for current vdev rx chainmask.
5619*5113495bSYour Name  *
5620*5113495bSYour Name  * @spectral: Pointer to Spectral object
5621*5113495bSYour Name  * @is_supported: Pointer to is_supported
5622*5113495bSYour Name  *
5623*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
5624*5113495bSYour Name  */
5625*5113495bSYour Name static QDF_STATUS
target_if_is_agile_supported_cur_chmask(struct target_if_spectral * spectral,bool * is_supported)5626*5113495bSYour Name target_if_is_agile_supported_cur_chmask(struct target_if_spectral *spectral,
5627*5113495bSYour Name 					bool *is_supported)
5628*5113495bSYour Name {
5629*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
5630*5113495bSYour Name 	uint8_t vdev_rxchainmask;
5631*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
5632*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev;
5633*5113495bSYour Name 	struct target_psoc_info *tgt_psoc_info;
5634*5113495bSYour Name 	struct wlan_psoc_host_service_ext_param *ext_svc_param;
5635*5113495bSYour Name 	struct wlan_psoc_host_mac_phy_caps *mac_phy_cap_arr = NULL;
5636*5113495bSYour Name 	struct wlan_psoc_host_mac_phy_caps *mac_phy_cap = NULL;
5637*5113495bSYour Name 	struct wlan_psoc_host_chainmask_table *table;
5638*5113495bSYour Name 	int j;
5639*5113495bSYour Name 	uint32_t table_id;
5640*5113495bSYour Name 	enum phy_ch_width ch_width;
5641*5113495bSYour Name 	uint8_t pdev_id;
5642*5113495bSYour Name 
5643*5113495bSYour Name 	if (!spectral) {
5644*5113495bSYour Name 		spectral_err("spectral target if object is null");
5645*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
5646*5113495bSYour Name 	}
5647*5113495bSYour Name 
5648*5113495bSYour Name 	if (!is_supported) {
5649*5113495bSYour Name 		spectral_err("is supported argument is null");
5650*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
5651*5113495bSYour Name 	}
5652*5113495bSYour Name 
5653*5113495bSYour Name 	if (spectral->spectral_gen <= SPECTRAL_GEN2) {
5654*5113495bSYour Name 		spectral_err("HW Agile mode is not supported up to gen 2");
5655*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
5656*5113495bSYour Name 	}
5657*5113495bSYour Name 
5658*5113495bSYour Name 	pdev = spectral->pdev_obj;
5659*5113495bSYour Name 	if (!pdev) {
5660*5113495bSYour Name 		spectral_err("pdev is null");
5661*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
5662*5113495bSYour Name 	}
5663*5113495bSYour Name 
5664*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
5665*5113495bSYour Name 	if (!psoc) {
5666*5113495bSYour Name 		spectral_err("psoc is null");
5667*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
5668*5113495bSYour Name 	}
5669*5113495bSYour Name 
5670*5113495bSYour Name 	vdev = target_if_spectral_get_vdev(spectral, SPECTRAL_SCAN_MODE_AGILE);
5671*5113495bSYour Name 	if (!vdev) {
5672*5113495bSYour Name 		spectral_err("First vdev is NULL");
5673*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
5674*5113495bSYour Name 	}
5675*5113495bSYour Name 
5676*5113495bSYour Name 	vdev_rxchainmask = wlan_vdev_mlme_get_rxchainmask(vdev);
5677*5113495bSYour Name 	if (!vdev_rxchainmask) {
5678*5113495bSYour Name 		spectral_err("vdev rx chainmask is zero");
5679*5113495bSYour Name 		wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
5680*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
5681*5113495bSYour Name 	}
5682*5113495bSYour Name 
5683*5113495bSYour Name 	ch_width = target_if_vdev_get_ch_width(vdev);
5684*5113495bSYour Name 	if (ch_width == CH_WIDTH_INVALID) {
5685*5113495bSYour Name 		spectral_err("Invalid channel width");
5686*5113495bSYour Name 		wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
5687*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
5688*5113495bSYour Name 	}
5689*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
5690*5113495bSYour Name 
5691*5113495bSYour Name 	tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc);
5692*5113495bSYour Name 	if (!tgt_psoc_info) {
5693*5113495bSYour Name 		spectral_err("target_psoc_info is null");
5694*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
5695*5113495bSYour Name 	}
5696*5113495bSYour Name 
5697*5113495bSYour Name 	ext_svc_param = target_psoc_get_service_ext_param(tgt_psoc_info);
5698*5113495bSYour Name 	if (!ext_svc_param) {
5699*5113495bSYour Name 		spectral_err("Extended service ready param null");
5700*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
5701*5113495bSYour Name 	}
5702*5113495bSYour Name 	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
5703*5113495bSYour Name 
5704*5113495bSYour Name 	mac_phy_cap_arr = target_psoc_get_mac_phy_cap(tgt_psoc_info);
5705*5113495bSYour Name 	if (!mac_phy_cap_arr) {
5706*5113495bSYour Name 		spectral_err("mac phy cap array is null");
5707*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
5708*5113495bSYour Name 	}
5709*5113495bSYour Name 
5710*5113495bSYour Name 	mac_phy_cap = &mac_phy_cap_arr[pdev_id];
5711*5113495bSYour Name 	if (!mac_phy_cap) {
5712*5113495bSYour Name 		spectral_err("mac phy cap is null");
5713*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
5714*5113495bSYour Name 	}
5715*5113495bSYour Name 
5716*5113495bSYour Name 	table_id = mac_phy_cap->chainmask_table_id;
5717*5113495bSYour Name 	table =  &ext_svc_param->chainmask_table[table_id];
5718*5113495bSYour Name 	if (!table) {
5719*5113495bSYour Name 		spectral_err("chainmask table not found");
5720*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
5721*5113495bSYour Name 	}
5722*5113495bSYour Name 
5723*5113495bSYour Name 	for (j = 0; j < table->num_valid_chainmasks; j++) {
5724*5113495bSYour Name 		if (table->cap_list[j].chainmask == vdev_rxchainmask) {
5725*5113495bSYour Name 			if (ch_width <= CH_WIDTH_80MHZ)
5726*5113495bSYour Name 				*is_supported =
5727*5113495bSYour Name 					table->cap_list[j].supports_aSpectral;
5728*5113495bSYour Name 			else
5729*5113495bSYour Name 				*is_supported =
5730*5113495bSYour Name 				      table->cap_list[j].supports_aSpectral_160;
5731*5113495bSYour Name 			break;
5732*5113495bSYour Name 		}
5733*5113495bSYour Name 	}
5734*5113495bSYour Name 
5735*5113495bSYour Name 	if (j == table->num_valid_chainmasks) {
5736*5113495bSYour Name 		spectral_err("vdev rx chainmask %u not found in table id = %u",
5737*5113495bSYour Name 			     vdev_rxchainmask, table_id);
5738*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
5739*5113495bSYour Name 	}
5740*5113495bSYour Name 
5741*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
5742*5113495bSYour Name }
5743*5113495bSYour Name 
5744*5113495bSYour Name #define INVALID_SPAN_NUM (-1)
5745*5113495bSYour Name /**
5746*5113495bSYour Name  * target_if_spectral_get_num_spans() - Get number of spans for a given sscan_bw
5747*5113495bSYour Name  * @pdev: Pointer to pdev object
5748*5113495bSYour Name  * @sscan_bw: Spectral scan bandwidth
5749*5113495bSYour Name  *
5750*5113495bSYour Name  * Return: Number of spans on success, INVALID_SPAN_NUM on failure
5751*5113495bSYour Name  */
5752*5113495bSYour Name static int
target_if_spectral_get_num_spans(struct wlan_objmgr_pdev * pdev,enum phy_ch_width sscan_bw)5753*5113495bSYour Name target_if_spectral_get_num_spans(
5754*5113495bSYour Name 		struct wlan_objmgr_pdev *pdev,
5755*5113495bSYour Name 		enum phy_ch_width sscan_bw)
5756*5113495bSYour Name {
5757*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
5758*5113495bSYour Name 	int num_spans;
5759*5113495bSYour Name 
5760*5113495bSYour Name 	if (!pdev) {
5761*5113495bSYour Name 		spectral_err_rl("pdev is null");
5762*5113495bSYour Name 		return INVALID_SPAN_NUM;
5763*5113495bSYour Name 	}
5764*5113495bSYour Name 
5765*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
5766*5113495bSYour Name 	if (!psoc) {
5767*5113495bSYour Name 		spectral_err_rl("psoc is null");
5768*5113495bSYour Name 		return INVALID_SPAN_NUM;
5769*5113495bSYour Name 	}
5770*5113495bSYour Name 
5771*5113495bSYour Name 	if (sscan_bw == CH_WIDTH_80P80MHZ) {
5772*5113495bSYour Name 		num_spans = 2;
5773*5113495bSYour Name 		if (wlan_psoc_nif_fw_ext_cap_get(
5774*5113495bSYour Name 		    psoc, WLAN_SOC_RESTRICTED_80P80_SUPPORT))
5775*5113495bSYour Name 			/* 5 MHz frequency span in restricted 80p80 case */
5776*5113495bSYour Name 			num_spans += 1;
5777*5113495bSYour Name 	} else {
5778*5113495bSYour Name 		num_spans = 1;
5779*5113495bSYour Name 	}
5780*5113495bSYour Name 
5781*5113495bSYour Name 	return num_spans;
5782*5113495bSYour Name }
5783*5113495bSYour Name 
5784*5113495bSYour Name #ifdef OPTIMIZED_SAMP_MESSAGE
5785*5113495bSYour Name /**
5786*5113495bSYour Name  * target_if_spectral_populate_session_report_info() - Populate per-session
5787*5113495bSYour Name  * report level information.
5788*5113495bSYour Name  *
5789*5113495bSYour Name  * @spectral: Pointer to Spectral object
5790*5113495bSYour Name  * @smode: Spectral scan mode
5791*5113495bSYour Name  *
5792*5113495bSYour Name  * Return: Success/Failure
5793*5113495bSYour Name  */
5794*5113495bSYour Name static QDF_STATUS
target_if_spectral_populate_session_report_info(struct target_if_spectral * spectral,enum spectral_scan_mode smode)5795*5113495bSYour Name target_if_spectral_populate_session_report_info(
5796*5113495bSYour Name 				struct target_if_spectral *spectral,
5797*5113495bSYour Name 				enum spectral_scan_mode smode)
5798*5113495bSYour Name {
5799*5113495bSYour Name 	struct per_session_report_info *rpt_info;
5800*5113495bSYour Name 
5801*5113495bSYour Name 	if (!spectral) {
5802*5113495bSYour Name 		spectral_err_rl("Spectral LMAC object is null");
5803*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
5804*5113495bSYour Name 	}
5805*5113495bSYour Name 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
5806*5113495bSYour Name 		spectral_err_rl("Invalid Spectral scan mode");
5807*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
5808*5113495bSYour Name 	}
5809*5113495bSYour Name 
5810*5113495bSYour Name 
5811*5113495bSYour Name 	qdf_spin_lock_bh(&spectral->session_report_info_lock);
5812*5113495bSYour Name 	/* Fill per-session report information, based on the spectral mode */
5813*5113495bSYour Name 	rpt_info = &spectral->report_info[smode];
5814*5113495bSYour Name 
5815*5113495bSYour Name 	rpt_info->operating_bw = spectral->ch_width[SPECTRAL_SCAN_MODE_NORMAL];
5816*5113495bSYour Name 	rpt_info->sscan_bw = spectral->ch_width[smode];
5817*5113495bSYour Name 	rpt_info->sscan_cfreq1 = spectral->params[smode].ss_frequency.cfreq1;
5818*5113495bSYour Name 	rpt_info->sscan_cfreq2 = spectral->params[smode].ss_frequency.cfreq2;
5819*5113495bSYour Name 	rpt_info->num_spans = target_if_spectral_get_num_spans(
5820*5113495bSYour Name 						spectral->pdev_obj,
5821*5113495bSYour Name 						rpt_info->sscan_bw);
5822*5113495bSYour Name 
5823*5113495bSYour Name 	if (rpt_info->num_spans == INVALID_SPAN_NUM) {
5824*5113495bSYour Name 		spectral_err_rl("Invalid number of spans: %u",
5825*5113495bSYour Name 				rpt_info->num_spans);
5826*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
5827*5113495bSYour Name 	}
5828*5113495bSYour Name 	rpt_info->valid = true;
5829*5113495bSYour Name 
5830*5113495bSYour Name 	qdf_spin_unlock_bh(&spectral->session_report_info_lock);
5831*5113495bSYour Name 
5832*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
5833*5113495bSYour Name }
5834*5113495bSYour Name 
5835*5113495bSYour Name /**
5836*5113495bSYour Name  * target_if_spectral_populate_session_det_host_info() - Populate per-session
5837*5113495bSYour Name  * detector level information that is known to the Host
5838*5113495bSYour Name  *
5839*5113495bSYour Name  * @spectral: Pointer to Spectral object
5840*5113495bSYour Name  * @smode: Spectral scan mode
5841*5113495bSYour Name  *
5842*5113495bSYour Name  * Return: Success/Failure
5843*5113495bSYour Name  */
5844*5113495bSYour Name static QDF_STATUS
target_if_spectral_populate_session_det_host_info(struct target_if_spectral * spectral,enum spectral_scan_mode smode)5845*5113495bSYour Name target_if_spectral_populate_session_det_host_info(
5846*5113495bSYour Name 				struct target_if_spectral *spectral,
5847*5113495bSYour Name 				enum spectral_scan_mode smode)
5848*5113495bSYour Name {
5849*5113495bSYour Name 	struct per_session_report_info *rpt_info;
5850*5113495bSYour Name 	struct sscan_detector_list *detector_list;
5851*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
5852*5113495bSYour Name 	uint16_t dest_det_idx = 0;
5853*5113495bSYour Name 	uint16_t dest_span_idx = 0;
5854*5113495bSYour Name 	bool is_sec80 = false;
5855*5113495bSYour Name 	uint8_t det, dest_det;
5856*5113495bSYour Name 
5857*5113495bSYour Name 	if (!spectral) {
5858*5113495bSYour Name 		spectral_err_rl("Spectral LMAC object is null");
5859*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
5860*5113495bSYour Name 	}
5861*5113495bSYour Name 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
5862*5113495bSYour Name 		spectral_err_rl("Invalid Spectral scan mode");
5863*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
5864*5113495bSYour Name 	}
5865*5113495bSYour Name 
5866*5113495bSYour Name 	if (!spectral->pdev_obj) {
5867*5113495bSYour Name 		spectral_err_rl("Spectral PDEV is null");
5868*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
5869*5113495bSYour Name 	}
5870*5113495bSYour Name 
5871*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(spectral->pdev_obj);
5872*5113495bSYour Name 	if (!psoc) {
5873*5113495bSYour Name 		spectral_err_rl("psoc is null");
5874*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
5875*5113495bSYour Name 	}
5876*5113495bSYour Name 
5877*5113495bSYour Name 	qdf_spin_lock_bh(&spectral->session_report_info_lock);
5878*5113495bSYour Name 	rpt_info = &spectral->report_info[smode];
5879*5113495bSYour Name 
5880*5113495bSYour Name 	qdf_spin_lock_bh(&spectral->detector_list_lock);
5881*5113495bSYour Name 	/* Fill per-sesion detector-level information */
5882*5113495bSYour Name 	detector_list = &spectral->detector_list[smode][rpt_info->sscan_bw];
5883*5113495bSYour Name 
5884*5113495bSYour Name 	for (det = 0; det < detector_list->num_detectors; det++) {
5885*5113495bSYour Name 		struct per_session_det_map *det_map;
5886*5113495bSYour Name 
5887*5113495bSYour Name 		qdf_spin_lock_bh(&spectral->session_det_map_lock);
5888*5113495bSYour Name 		det_map = &spectral->det_map[detector_list->detectors[det]];
5889*5113495bSYour Name 		if (detector_list->num_detectors > 1) {
5890*5113495bSYour Name 			if (det == 0) {
5891*5113495bSYour Name 				det_map->buf_type = SPECTRAL_MSG_BUF_NEW;
5892*5113495bSYour Name 				det_map->send_to_upper_layers = false;
5893*5113495bSYour Name 			} else if (det == detector_list->num_detectors - 1) {
5894*5113495bSYour Name 				det_map->buf_type = SPECTRAL_MSG_BUF_SAVED;
5895*5113495bSYour Name 				det_map->send_to_upper_layers = true;
5896*5113495bSYour Name 			} else {
5897*5113495bSYour Name 				/* middle fragments */
5898*5113495bSYour Name 				det_map->buf_type = SPECTRAL_MSG_BUF_SAVED;
5899*5113495bSYour Name 				det_map->send_to_upper_layers = false;
5900*5113495bSYour Name 			}
5901*5113495bSYour Name 		} else {
5902*5113495bSYour Name 			det_map->buf_type = SPECTRAL_MSG_BUF_NEW;
5903*5113495bSYour Name 			det_map->send_to_upper_layers = true;
5904*5113495bSYour Name 		}
5905*5113495bSYour Name 
5906*5113495bSYour Name 		det_map->num_dest_det_info = 1;
5907*5113495bSYour Name 		if (rpt_info->sscan_bw == CH_WIDTH_80P80MHZ &&
5908*5113495bSYour Name 		    wlan_psoc_nif_fw_ext_cap_get(
5909*5113495bSYour Name 		    psoc, WLAN_SOC_RESTRICTED_80P80_SUPPORT)) {
5910*5113495bSYour Name 			/**
5911*5113495bSYour Name 			 * In 165MHz case, 1 Spectral HW detector maps to 3
5912*5113495bSYour Name 			 * detectors in SAMP msg.
5913*5113495bSYour Name 			 */
5914*5113495bSYour Name 			det_map->num_dest_det_info += 2;
5915*5113495bSYour Name 		}
5916*5113495bSYour Name 
5917*5113495bSYour Name 		for (dest_det = 0; dest_det < det_map->num_dest_det_info;
5918*5113495bSYour Name 		     dest_det++) {
5919*5113495bSYour Name 			struct per_session_dest_det_info *map_det_info;
5920*5113495bSYour Name 
5921*5113495bSYour Name 			map_det_info = &det_map->dest_det_info[dest_det];
5922*5113495bSYour Name 			map_det_info->freq_span_id = dest_span_idx;
5923*5113495bSYour Name 			map_det_info->det_id = dest_det_idx;
5924*5113495bSYour Name 			map_det_info->is_sec80 = is_sec80;
5925*5113495bSYour Name 			if (rpt_info->sscan_bw == CH_WIDTH_80P80MHZ) {
5926*5113495bSYour Name 			/* Increment span ID for non-contiguous modes */
5927*5113495bSYour Name 				dest_det_idx = 0;
5928*5113495bSYour Name 				dest_span_idx++;
5929*5113495bSYour Name 			} else {
5930*5113495bSYour Name 			/* Increment detector ID for contiguous modes */
5931*5113495bSYour Name 				dest_det_idx++;
5932*5113495bSYour Name 			}
5933*5113495bSYour Name 			is_sec80 = !is_sec80;
5934*5113495bSYour Name 		}
5935*5113495bSYour Name 		det_map->det_map_valid[smode] = true;
5936*5113495bSYour Name 		qdf_spin_unlock_bh(&spectral->session_det_map_lock);
5937*5113495bSYour Name 	}
5938*5113495bSYour Name 	qdf_spin_unlock_bh(&spectral->detector_list_lock);
5939*5113495bSYour Name 	qdf_spin_unlock_bh(&spectral->session_report_info_lock);
5940*5113495bSYour Name 
5941*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
5942*5113495bSYour Name }
5943*5113495bSYour Name 
5944*5113495bSYour Name #else
5945*5113495bSYour Name static QDF_STATUS
target_if_spectral_populate_session_report_info(struct target_if_spectral * spectral,enum spectral_scan_mode smode)5946*5113495bSYour Name target_if_spectral_populate_session_report_info(
5947*5113495bSYour Name 				struct target_if_spectral *spectral,
5948*5113495bSYour Name 				enum spectral_scan_mode smode)
5949*5113495bSYour Name {
5950*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
5951*5113495bSYour Name }
5952*5113495bSYour Name 
5953*5113495bSYour Name static QDF_STATUS
target_if_spectral_populate_session_det_host_info(struct target_if_spectral * spectral,enum spectral_scan_mode smode)5954*5113495bSYour Name target_if_spectral_populate_session_det_host_info(
5955*5113495bSYour Name 				struct target_if_spectral *spectral,
5956*5113495bSYour Name 				enum spectral_scan_mode smode)
5957*5113495bSYour Name {
5958*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
5959*5113495bSYour Name }
5960*5113495bSYour Name #endif /* OPTIMIZED_SAMP_MESSAGE */
5961*5113495bSYour Name 
5962*5113495bSYour Name QDF_STATUS
spectral_is_session_info_expected_from_target(struct wlan_objmgr_pdev * pdev,bool * is_session_info_expected)5963*5113495bSYour Name spectral_is_session_info_expected_from_target(struct wlan_objmgr_pdev *pdev,
5964*5113495bSYour Name 					      bool *is_session_info_expected)
5965*5113495bSYour Name {
5966*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
5967*5113495bSYour Name 	struct wmi_unified *wmi_handle;
5968*5113495bSYour Name 
5969*5113495bSYour Name 	if (!pdev) {
5970*5113495bSYour Name 		spectral_err("pdev is null");
5971*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
5972*5113495bSYour Name 	}
5973*5113495bSYour Name 
5974*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
5975*5113495bSYour Name 	if (!psoc) {
5976*5113495bSYour Name 		spectral_err("psoc is null");
5977*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
5978*5113495bSYour Name 	}
5979*5113495bSYour Name 
5980*5113495bSYour Name 	wmi_handle =  get_wmi_unified_hdl_from_psoc(psoc);
5981*5113495bSYour Name 	if (!wmi_handle) {
5982*5113495bSYour Name 		spectral_err("wmi handle is null");
5983*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
5984*5113495bSYour Name 	}
5985*5113495bSYour Name 
5986*5113495bSYour Name 	*is_session_info_expected = target_if_spectral_wmi_service_enabled(
5987*5113495bSYour Name 				psoc, wmi_handle,
5988*5113495bSYour Name 				wmi_service_spectral_session_info_support);
5989*5113495bSYour Name 
5990*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
5991*5113495bSYour Name }
5992*5113495bSYour Name 
5993*5113495bSYour Name QDF_STATUS
target_if_start_spectral_scan(struct wlan_objmgr_pdev * pdev,uint8_t vdev_id,const enum spectral_scan_mode smode,enum spectral_cp_error_code * err)5994*5113495bSYour Name target_if_start_spectral_scan(struct wlan_objmgr_pdev *pdev,
5995*5113495bSYour Name 			      uint8_t vdev_id,
5996*5113495bSYour Name 			      const enum spectral_scan_mode smode,
5997*5113495bSYour Name 			      enum spectral_cp_error_code *err)
5998*5113495bSYour Name {
5999*5113495bSYour Name 	struct target_if_spectral_ops *p_sops;
6000*5113495bSYour Name 	struct target_if_spectral *spectral;
6001*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
6002*5113495bSYour Name 	enum reg_wifi_band band;
6003*5113495bSYour Name 	QDF_STATUS ret;
6004*5113495bSYour Name 	bool is_session_info_expected;
6005*5113495bSYour Name 
6006*5113495bSYour Name 	if (!err) {
6007*5113495bSYour Name 		spectral_err("Error code argument is null");
6008*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
6009*5113495bSYour Name 	}
6010*5113495bSYour Name 	*err = SPECTRAL_SCAN_ERR_INVALID;
6011*5113495bSYour Name 
6012*5113495bSYour Name 	if (!pdev) {
6013*5113495bSYour Name 		spectral_err("pdev object is NUll");
6014*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
6015*5113495bSYour Name 	}
6016*5113495bSYour Name 
6017*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
6018*5113495bSYour Name 	if (!psoc) {
6019*5113495bSYour Name 		spectral_err("psoc is null");
6020*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
6021*5113495bSYour Name 	}
6022*5113495bSYour Name 
6023*5113495bSYour Name 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
6024*5113495bSYour Name 		*err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED;
6025*5113495bSYour Name 		spectral_err("Invalid Spectral mode %u", smode);
6026*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
6027*5113495bSYour Name 	}
6028*5113495bSYour Name 
6029*5113495bSYour Name 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
6030*5113495bSYour Name 	if (!spectral) {
6031*5113495bSYour Name 		spectral_err("Spectral LMAC object is NUll");
6032*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
6033*5113495bSYour Name 	}
6034*5113495bSYour Name 
6035*5113495bSYour Name 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
6036*5113495bSYour Name 	if (!p_sops) {
6037*5113495bSYour Name 		spectral_err("p_sops is null");
6038*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
6039*5113495bSYour Name 	}
6040*5113495bSYour Name 
6041*5113495bSYour Name 	if (p_sops->is_spectral_active(spectral, smode)) {
6042*5113495bSYour Name 		spectral_err("spectral in progress in current pdev, mode %d",
6043*5113495bSYour Name 			     smode);
6044*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
6045*5113495bSYour Name 	}
6046*5113495bSYour Name 	spectral->vdev_id[smode] = vdev_id;
6047*5113495bSYour Name 
6048*5113495bSYour Name 	if (smode == SPECTRAL_SCAN_MODE_AGILE) {
6049*5113495bSYour Name 		QDF_STATUS status;
6050*5113495bSYour Name 		bool is_supported = false;
6051*5113495bSYour Name 
6052*5113495bSYour Name 		status = target_if_is_agile_supported_cur_chmask(spectral,
6053*5113495bSYour Name 								 &is_supported);
6054*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
6055*5113495bSYour Name 			*err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED;
6056*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
6057*5113495bSYour Name 		}
6058*5113495bSYour Name 
6059*5113495bSYour Name 		if (!is_supported) {
6060*5113495bSYour Name 			spectral_err("aSpectral unsupported for cur chainmask");
6061*5113495bSYour Name 			*err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED;
6062*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
6063*5113495bSYour Name 		}
6064*5113495bSYour Name 	}
6065*5113495bSYour Name 
6066*5113495bSYour Name 	band = target_if_get_curr_band(spectral->pdev_obj, vdev_id);
6067*5113495bSYour Name 	if (band == REG_BAND_UNKNOWN) {
6068*5113495bSYour Name 		spectral_err("Failed to get current band");
6069*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
6070*5113495bSYour Name 	}
6071*5113495bSYour Name 	if ((band == REG_BAND_5G) && (smode == SPECTRAL_SCAN_MODE_AGILE)) {
6072*5113495bSYour Name 		struct target_psoc_info *tgt_hdl;
6073*5113495bSYour Name 		enum wmi_host_hw_mode_config_type mode;
6074*5113495bSYour Name 		bool is_agile_scan_inprog_5g_pdev;
6075*5113495bSYour Name 
6076*5113495bSYour Name 		tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc);
6077*5113495bSYour Name 		if (!tgt_hdl) {
6078*5113495bSYour Name 			target_if_err("target_psoc_info is null");
6079*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
6080*5113495bSYour Name 		}
6081*5113495bSYour Name 
6082*5113495bSYour Name 		mode = target_psoc_get_preferred_hw_mode(tgt_hdl);
6083*5113495bSYour Name 		switch (mode) {
6084*5113495bSYour Name 		case WMI_HOST_HW_MODE_SBS_PASSIVE:
6085*5113495bSYour Name 		case WMI_HOST_HW_MODE_SBS:
6086*5113495bSYour Name 		case WMI_HOST_HW_MODE_DBS_SBS:
6087*5113495bSYour Name 		case WMI_HOST_HW_MODE_DBS_OR_SBS:
6088*5113495bSYour Name 			is_agile_scan_inprog_5g_pdev = false;
6089*5113495bSYour Name 			wlan_objmgr_iterate_obj_list
6090*5113495bSYour Name 				(psoc, WLAN_PDEV_OP,
6091*5113495bSYour Name 				 target_if_is_agile_scan_active_in_5g,
6092*5113495bSYour Name 				 &is_agile_scan_inprog_5g_pdev, 0,
6093*5113495bSYour Name 				 WLAN_SPECTRAL_ID);
6094*5113495bSYour Name 			break;
6095*5113495bSYour Name 		default:
6096*5113495bSYour Name 			is_agile_scan_inprog_5g_pdev = false;
6097*5113495bSYour Name 			break;
6098*5113495bSYour Name 		}
6099*5113495bSYour Name 
6100*5113495bSYour Name 		if (is_agile_scan_inprog_5g_pdev) {
6101*5113495bSYour Name 			spectral_err("Agile Scan in progress in one of the SBS 5G pdev");
6102*5113495bSYour Name 			*err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED;
6103*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
6104*5113495bSYour Name 		}
6105*5113495bSYour Name 	}
6106*5113495bSYour Name 
6107*5113495bSYour Name 	if (smode == SPECTRAL_SCAN_MODE_AGILE) {
6108*5113495bSYour Name 		bool is_aspectral_prohibited = false;
6109*5113495bSYour Name 		QDF_STATUS status;
6110*5113495bSYour Name 
6111*5113495bSYour Name 		status = wlan_objmgr_iterate_obj_list
6112*5113495bSYour Name 				(psoc, WLAN_PDEV_OP,
6113*5113495bSYour Name 				 target_if_is_aspectral_prohibited_by_adfs,
6114*5113495bSYour Name 				 &is_aspectral_prohibited, 0,
6115*5113495bSYour Name 				 WLAN_SPECTRAL_ID);
6116*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
6117*5113495bSYour Name 			spectral_err("Failed to iterate over pdevs");
6118*5113495bSYour Name 			*err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED;
6119*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
6120*5113495bSYour Name 		}
6121*5113495bSYour Name 
6122*5113495bSYour Name 		if (is_aspectral_prohibited) {
6123*5113495bSYour Name 			*err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED;
6124*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
6125*5113495bSYour Name 		}
6126*5113495bSYour Name 	}
6127*5113495bSYour Name 
6128*5113495bSYour Name 	if (!spectral->params_valid[smode]) {
6129*5113495bSYour Name 		target_if_spectral_info_read(spectral,
6130*5113495bSYour Name 					     smode,
6131*5113495bSYour Name 					     TARGET_IF_SPECTRAL_INFO_PARAMS,
6132*5113495bSYour Name 					     &spectral->params[smode],
6133*5113495bSYour Name 					     sizeof(spectral->params[smode]));
6134*5113495bSYour Name 		spectral->params_valid[smode] = true;
6135*5113495bSYour Name 	}
6136*5113495bSYour Name 
6137*5113495bSYour Name 	qdf_spin_lock_bh(&spectral->spectral_lock);
6138*5113495bSYour Name 	if (smode == SPECTRAL_SCAN_MODE_AGILE) {
6139*5113495bSYour Name 		QDF_STATUS status;
6140*5113495bSYour Name 		bool is_overlapping;
6141*5113495bSYour Name 		enum phy_ch_width ch_width[SPECTRAL_SCAN_MODE_MAX];
6142*5113495bSYour Name 		enum spectral_scan_mode m;
6143*5113495bSYour Name 		enum phy_ch_width agile_ch_width;
6144*5113495bSYour Name 
6145*5113495bSYour Name 		m = SPECTRAL_SCAN_MODE_NORMAL;
6146*5113495bSYour Name 		for (; m < SPECTRAL_SCAN_MODE_MAX; m++)
6147*5113495bSYour Name 			ch_width[m] = CH_WIDTH_INVALID;
6148*5113495bSYour Name 		status = target_if_spectral_populate_chwidth
6149*5113495bSYour Name 			(spectral, ch_width, spectral->params
6150*5113495bSYour Name 			 [SPECTRAL_SCAN_MODE_AGILE].ss_frequency.cfreq2 > 0);
6151*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
6152*5113495bSYour Name 			qdf_spin_unlock_bh(&spectral->spectral_lock);
6153*5113495bSYour Name 			spectral_err("Failed to populate channel width");
6154*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
6155*5113495bSYour Name 		}
6156*5113495bSYour Name 		agile_ch_width = ch_width[SPECTRAL_SCAN_MODE_AGILE];
6157*5113495bSYour Name 
6158*5113495bSYour Name 		if (!spectral->params[smode].ss_frequency.cfreq1) {
6159*5113495bSYour Name 			*err = SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED;
6160*5113495bSYour Name 			qdf_spin_unlock_bh(&spectral->spectral_lock);
6161*5113495bSYour Name 			spectral_err("Agile Spectral cfreq1 is 0");
6162*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
6163*5113495bSYour Name 		} else if (agile_ch_width == CH_WIDTH_80P80MHZ &&
6164*5113495bSYour Name 			   !spectral->params[smode].ss_frequency.cfreq2) {
6165*5113495bSYour Name 			*err = SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED;
6166*5113495bSYour Name 			qdf_spin_unlock_bh(&spectral->spectral_lock);
6167*5113495bSYour Name 			spectral_err("Agile Spectral cfreq2 is 0");
6168*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
6169*5113495bSYour Name 		}
6170*5113495bSYour Name 
6171*5113495bSYour Name 		status = target_if_is_agile_span_overlap_with_operating_span
6172*5113495bSYour Name 				(spectral, ch_width,
6173*5113495bSYour Name 				 &spectral->params[smode].ss_frequency,
6174*5113495bSYour Name 				 &is_overlapping);
6175*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
6176*5113495bSYour Name 			qdf_spin_unlock_bh(&spectral->spectral_lock);
6177*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
6178*5113495bSYour Name 		}
6179*5113495bSYour Name 
6180*5113495bSYour Name 		if (is_overlapping) {
6181*5113495bSYour Name 			*err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
6182*5113495bSYour Name 			qdf_spin_unlock_bh(&spectral->spectral_lock);
6183*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
6184*5113495bSYour Name 		}
6185*5113495bSYour Name 	}
6186*5113495bSYour Name 
6187*5113495bSYour Name 	/* Populate detectot list first */
6188*5113495bSYour Name 	ret = target_if_spectral_detector_list_init(spectral);
6189*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(ret)) {
6190*5113495bSYour Name 		qdf_spin_unlock_bh(&spectral->spectral_lock);
6191*5113495bSYour Name 		spectral_err("Failed to initialize detector list");
6192*5113495bSYour Name 		return ret;
6193*5113495bSYour Name 	}
6194*5113495bSYour Name 
6195*5113495bSYour Name 	ret = target_if_spectral_populate_chwidth(
6196*5113495bSYour Name 			spectral, spectral->ch_width,
6197*5113495bSYour Name 			spectral->params[SPECTRAL_SCAN_MODE_AGILE].
6198*5113495bSYour Name 			ss_frequency.cfreq2 > 0);
6199*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(ret)) {
6200*5113495bSYour Name 		qdf_spin_unlock_bh(&spectral->spectral_lock);
6201*5113495bSYour Name 		spectral_err("Failed to get channel widths");
6202*5113495bSYour Name 		return ret;
6203*5113495bSYour Name 	}
6204*5113495bSYour Name 
6205*5113495bSYour Name 	ret = spectral_is_session_info_expected_from_target(
6206*5113495bSYour Name 				spectral->pdev_obj,
6207*5113495bSYour Name 				&is_session_info_expected);
6208*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(ret)) {
6209*5113495bSYour Name 		qdf_spin_unlock_bh(&spectral->spectral_lock);
6210*5113495bSYour Name 		spectral_err("Failed to check if session info is expected");
6211*5113495bSYour Name 		return ret;
6212*5113495bSYour Name 	}
6213*5113495bSYour Name 
6214*5113495bSYour Name 	/* If FW doesn't send session info, populate it */
6215*5113495bSYour Name 	if (!is_session_info_expected) {
6216*5113495bSYour Name 		ret = target_if_spectral_populate_session_report_info(spectral,
6217*5113495bSYour Name 								      smode);
6218*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(ret)) {
6219*5113495bSYour Name 			qdf_spin_unlock_bh(&spectral->spectral_lock);
6220*5113495bSYour Name 			spectral_err("Failed to populate per-session report info");
6221*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
6222*5113495bSYour Name 		}
6223*5113495bSYour Name 
6224*5113495bSYour Name 		ret = target_if_spectral_populate_session_det_host_info(
6225*5113495bSYour Name 					spectral, smode);
6226*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(ret)) {
6227*5113495bSYour Name 			qdf_spin_unlock_bh(&spectral->spectral_lock);
6228*5113495bSYour Name 			spectral_err("Failed to populate per-session detector info");
6229*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
6230*5113495bSYour Name 		}
6231*5113495bSYour Name 	}
6232*5113495bSYour Name 
6233*5113495bSYour Name 	target_if_spectral_scan_enable_params(spectral,
6234*5113495bSYour Name 					      &spectral->params[smode], smode,
6235*5113495bSYour Name 					      err);
6236*5113495bSYour Name 
6237*5113495bSYour Name 	spectral->sscan_width_configured[smode] = false;
6238*5113495bSYour Name 	qdf_spin_unlock_bh(&spectral->spectral_lock);
6239*5113495bSYour Name 
6240*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
6241*5113495bSYour Name }
6242*5113495bSYour Name 
6243*5113495bSYour Name QDF_STATUS
target_if_stop_spectral_scan(struct wlan_objmgr_pdev * pdev,const enum spectral_scan_mode smode,enum spectral_cp_error_code * err)6244*5113495bSYour Name target_if_stop_spectral_scan(struct wlan_objmgr_pdev *pdev,
6245*5113495bSYour Name 			     const enum spectral_scan_mode smode,
6246*5113495bSYour Name 			     enum spectral_cp_error_code *err)
6247*5113495bSYour Name {
6248*5113495bSYour Name 	struct target_if_spectral_ops *p_sops;
6249*5113495bSYour Name 	struct target_if_spectral *spectral;
6250*5113495bSYour Name 	uint8_t det;
6251*5113495bSYour Name 
6252*5113495bSYour Name 	if (!pdev) {
6253*5113495bSYour Name 		spectral_err("pdev object is NULL");
6254*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
6255*5113495bSYour Name 	}
6256*5113495bSYour Name 
6257*5113495bSYour Name 	if (target_if_spectral_is_feature_disabled_pdev(pdev)) {
6258*5113495bSYour Name 		spectral_info("Spectral feature is disabled");
6259*5113495bSYour Name 		return QDF_STATUS_COMP_DISABLED;
6260*5113495bSYour Name 	}
6261*5113495bSYour Name 
6262*5113495bSYour Name 	if (!err) {
6263*5113495bSYour Name 		spectral_err("Error code argument is null");
6264*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
6265*5113495bSYour Name 	}
6266*5113495bSYour Name 	*err = SPECTRAL_SCAN_ERR_INVALID;
6267*5113495bSYour Name 
6268*5113495bSYour Name 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
6269*5113495bSYour Name 		*err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED;
6270*5113495bSYour Name 		spectral_err("Invalid Spectral mode %u", smode);
6271*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
6272*5113495bSYour Name 	}
6273*5113495bSYour Name 
6274*5113495bSYour Name 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
6275*5113495bSYour Name 	if (!spectral) {
6276*5113495bSYour Name 		spectral_err("Spectral LMAC object is NUll ");
6277*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
6278*5113495bSYour Name 	}
6279*5113495bSYour Name 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
6280*5113495bSYour Name 
6281*5113495bSYour Name 	qdf_spin_lock_bh(&spectral->spectral_lock);
6282*5113495bSYour Name 	p_sops->stop_spectral_scan(spectral, smode);
6283*5113495bSYour Name 	if (spectral->classify_scan) {
6284*5113495bSYour Name 		/* TODO : Check if this logic is necessary */
6285*5113495bSYour Name 		spectral->detects_control_channel = 0;
6286*5113495bSYour Name 		spectral->detects_extension_channel = 0;
6287*5113495bSYour Name 		spectral->detects_above_dc = 0;
6288*5113495bSYour Name 		spectral->detects_below_dc = 0;
6289*5113495bSYour Name 		spectral->classify_scan = 0;
6290*5113495bSYour Name 	}
6291*5113495bSYour Name 
6292*5113495bSYour Name 	spectral->send_single_packet = 0;
6293*5113495bSYour Name 	spectral->sc_spectral_scan = 0;
6294*5113495bSYour Name 
6295*5113495bSYour Name 	qdf_spin_lock_bh(&spectral->session_det_map_lock);
6296*5113495bSYour Name 	for (det = 0; det < MAX_DETECTORS_PER_PDEV; det++)
6297*5113495bSYour Name 		spectral->det_map[det].det_map_valid[smode] = false;
6298*5113495bSYour Name 
6299*5113495bSYour Name 	qdf_spin_unlock_bh(&spectral->session_det_map_lock);
6300*5113495bSYour Name 
6301*5113495bSYour Name 	/* Mark report info as invalid */
6302*5113495bSYour Name 	qdf_spin_lock_bh(&spectral->session_report_info_lock);
6303*5113495bSYour Name 	spectral->report_info[smode].valid = false;
6304*5113495bSYour Name 	qdf_spin_unlock_bh(&spectral->session_report_info_lock);
6305*5113495bSYour Name 
6306*5113495bSYour Name 	qdf_spin_unlock_bh(&spectral->spectral_lock);
6307*5113495bSYour Name 
6308*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
6309*5113495bSYour Name }
6310*5113495bSYour Name 
6311*5113495bSYour Name /**
6312*5113495bSYour Name  * target_if_is_spectral_active() - Get whether Spectral is active
6313*5113495bSYour Name  * @pdev: Pointer to pdev object
6314*5113495bSYour Name  * @smode: Spectral scan mode
6315*5113495bSYour Name  *
6316*5113495bSYour Name  * API to get whether Spectral is active
6317*5113495bSYour Name  *
6318*5113495bSYour Name  * Return: True if Spectral is active, false if Spectral is not active
6319*5113495bSYour Name  */
6320*5113495bSYour Name bool
target_if_is_spectral_active(struct wlan_objmgr_pdev * pdev,const enum spectral_scan_mode smode)6321*5113495bSYour Name target_if_is_spectral_active(struct wlan_objmgr_pdev *pdev,
6322*5113495bSYour Name 			     const enum spectral_scan_mode smode)
6323*5113495bSYour Name {
6324*5113495bSYour Name 	struct target_if_spectral *spectral = NULL;
6325*5113495bSYour Name 	struct target_if_spectral_ops *p_sops = NULL;
6326*5113495bSYour Name 
6327*5113495bSYour Name 	if (!pdev) {
6328*5113495bSYour Name 		spectral_err("pdev is null");
6329*5113495bSYour Name 		return false;
6330*5113495bSYour Name 	}
6331*5113495bSYour Name 
6332*5113495bSYour Name 	if (target_if_spectral_is_feature_disabled_pdev(pdev)) {
6333*5113495bSYour Name 		spectral_info("Spectral feature is disabled");
6334*5113495bSYour Name 		return false;
6335*5113495bSYour Name 	}
6336*5113495bSYour Name 
6337*5113495bSYour Name 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
6338*5113495bSYour Name 
6339*5113495bSYour Name 	if (!spectral) {
6340*5113495bSYour Name 		spectral_err("SPECTRAL : Module doesn't exist");
6341*5113495bSYour Name 		return false;
6342*5113495bSYour Name 	}
6343*5113495bSYour Name 
6344*5113495bSYour Name 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
6345*5113495bSYour Name 
6346*5113495bSYour Name 	if (!p_sops) {
6347*5113495bSYour Name 		spectral_err("p_sops is null");
6348*5113495bSYour Name 		return false;
6349*5113495bSYour Name 	}
6350*5113495bSYour Name 
6351*5113495bSYour Name 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
6352*5113495bSYour Name 		spectral_err("Invalid Spectral mode %u", smode);
6353*5113495bSYour Name 		return false;
6354*5113495bSYour Name 	}
6355*5113495bSYour Name 
6356*5113495bSYour Name 	return p_sops->is_spectral_active(spectral, smode);
6357*5113495bSYour Name }
6358*5113495bSYour Name 
6359*5113495bSYour Name /**
6360*5113495bSYour Name  * target_if_is_spectral_enabled() - Get whether Spectral is enabled
6361*5113495bSYour Name  * @pdev: Pointer to pdev object
6362*5113495bSYour Name  * @smode: Spectral scan mode
6363*5113495bSYour Name  *
6364*5113495bSYour Name  * API to get whether Spectral is enabled
6365*5113495bSYour Name  *
6366*5113495bSYour Name  * Return: True if Spectral is enabled, false if Spectral is not enabled
6367*5113495bSYour Name  */
6368*5113495bSYour Name bool
target_if_is_spectral_enabled(struct wlan_objmgr_pdev * pdev,enum spectral_scan_mode smode)6369*5113495bSYour Name target_if_is_spectral_enabled(struct wlan_objmgr_pdev *pdev,
6370*5113495bSYour Name 			      enum spectral_scan_mode smode)
6371*5113495bSYour Name {
6372*5113495bSYour Name 	struct target_if_spectral *spectral = NULL;
6373*5113495bSYour Name 	struct target_if_spectral_ops *p_sops = NULL;
6374*5113495bSYour Name 
6375*5113495bSYour Name 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
6376*5113495bSYour Name 
6377*5113495bSYour Name 	if (!spectral) {
6378*5113495bSYour Name 		spectral_err("SPECTRAL : Module doesn't exist");
6379*5113495bSYour Name 		return false;
6380*5113495bSYour Name 	}
6381*5113495bSYour Name 
6382*5113495bSYour Name 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
6383*5113495bSYour Name 
6384*5113495bSYour Name 	if (!p_sops) {
6385*5113495bSYour Name 		spectral_err("p_sops is null");
6386*5113495bSYour Name 		return false;
6387*5113495bSYour Name 	}
6388*5113495bSYour Name 
6389*5113495bSYour Name 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
6390*5113495bSYour Name 		spectral_err("Invalid Spectral mode %u", smode);
6391*5113495bSYour Name 		return false;
6392*5113495bSYour Name 	}
6393*5113495bSYour Name 
6394*5113495bSYour Name 	return p_sops->is_spectral_enabled(spectral, smode);
6395*5113495bSYour Name }
6396*5113495bSYour Name 
6397*5113495bSYour Name #ifdef DIRECT_BUF_RX_DEBUG
6398*5113495bSYour Name /**
6399*5113495bSYour Name  * target_if_spectral_do_dbr_ring_debug() - Start/Stop Spectral DMA ring debug
6400*5113495bSYour Name  * @pdev: Pointer to pdev object
6401*5113495bSYour Name  * @enable: Enable/Disable Spectral DMA ring debug
6402*5113495bSYour Name  *
6403*5113495bSYour Name  * Start/stop Spectral DMA ring debug based on @enable.
6404*5113495bSYour Name  * Also save the state for future use.
6405*5113495bSYour Name  *
6406*5113495bSYour Name  * Return: QDF_STATUS of operation
6407*5113495bSYour Name  */
6408*5113495bSYour Name static QDF_STATUS
target_if_spectral_do_dbr_ring_debug(struct wlan_objmgr_pdev * pdev,bool enable)6409*5113495bSYour Name target_if_spectral_do_dbr_ring_debug(struct wlan_objmgr_pdev *pdev, bool enable)
6410*5113495bSYour Name {
6411*5113495bSYour Name 	struct target_if_spectral *spectral;
6412*5113495bSYour Name 	struct wlan_lmac_if_tx_ops *tx_ops;
6413*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
6414*5113495bSYour Name 
6415*5113495bSYour Name 	if (!pdev)
6416*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
6417*5113495bSYour Name 
6418*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
6419*5113495bSYour Name 	if (!psoc) {
6420*5113495bSYour Name 		spectral_err("psoc is null");
6421*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
6422*5113495bSYour Name 	}
6423*5113495bSYour Name 
6424*5113495bSYour Name 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
6425*5113495bSYour Name 	if (!tx_ops) {
6426*5113495bSYour Name 		spectral_err("tx_ops is NULL");
6427*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
6428*5113495bSYour Name 	}
6429*5113495bSYour Name 
6430*5113495bSYour Name 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
6431*5113495bSYour Name 	if (!spectral) {
6432*5113495bSYour Name 		spectral_err("Spectal LMAC object is NULL");
6433*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
6434*5113495bSYour Name 	}
6435*5113495bSYour Name 
6436*5113495bSYour Name 	/* Save the state */
6437*5113495bSYour Name 	spectral->dbr_ring_debug = enable;
6438*5113495bSYour Name 
6439*5113495bSYour Name 	if (enable)
6440*5113495bSYour Name 		return tx_ops->dbr_tx_ops.direct_buf_rx_start_ring_debug(
6441*5113495bSYour Name 				pdev, 0, SPECTRAL_DBR_RING_DEBUG_SIZE);
6442*5113495bSYour Name 	else
6443*5113495bSYour Name 		return tx_ops->dbr_tx_ops.direct_buf_rx_stop_ring_debug(
6444*5113495bSYour Name 				pdev, 0);
6445*5113495bSYour Name 
6446*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
6447*5113495bSYour Name }
6448*5113495bSYour Name 
6449*5113495bSYour Name /**
6450*5113495bSYour Name  * target_if_spectral_do_dbr_buff_debug() - Start/Stop Spectral DMA buffer debug
6451*5113495bSYour Name  * @pdev: Pointer to pdev object
6452*5113495bSYour Name  * @enable: Enable/Disable Spectral DMA buffer debug
6453*5113495bSYour Name  *
6454*5113495bSYour Name  * Start/stop Spectral DMA buffer debug based on @enable.
6455*5113495bSYour Name  * Also save the state for future use.
6456*5113495bSYour Name  *
6457*5113495bSYour Name  * Return: QDF_STATUS of operation
6458*5113495bSYour Name  */
6459*5113495bSYour Name static QDF_STATUS
target_if_spectral_do_dbr_buff_debug(struct wlan_objmgr_pdev * pdev,bool enable)6460*5113495bSYour Name target_if_spectral_do_dbr_buff_debug(struct wlan_objmgr_pdev *pdev, bool enable)
6461*5113495bSYour Name {
6462*5113495bSYour Name 	struct target_if_spectral *spectral;
6463*5113495bSYour Name 	struct wlan_lmac_if_tx_ops *tx_ops;
6464*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
6465*5113495bSYour Name 
6466*5113495bSYour Name 	if (!pdev)
6467*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
6468*5113495bSYour Name 
6469*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
6470*5113495bSYour Name 	if (!psoc) {
6471*5113495bSYour Name 		spectral_err("psoc is null");
6472*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
6473*5113495bSYour Name 	}
6474*5113495bSYour Name 
6475*5113495bSYour Name 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
6476*5113495bSYour Name 	if (!tx_ops) {
6477*5113495bSYour Name 		spectral_err("tx_ops is NULL");
6478*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
6479*5113495bSYour Name 	}
6480*5113495bSYour Name 
6481*5113495bSYour Name 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
6482*5113495bSYour Name 	if (!spectral) {
6483*5113495bSYour Name 		spectral_err("Spectal LMAC object is NULL");
6484*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
6485*5113495bSYour Name 	}
6486*5113495bSYour Name 
6487*5113495bSYour Name 	/* Save the state */
6488*5113495bSYour Name 	spectral->dbr_buff_debug = enable;
6489*5113495bSYour Name 
6490*5113495bSYour Name 	if (enable)
6491*5113495bSYour Name 		return tx_ops->dbr_tx_ops.direct_buf_rx_start_buffer_poisoning(
6492*5113495bSYour Name 				pdev, 0, MEM_POISON_SIGNATURE);
6493*5113495bSYour Name 	else
6494*5113495bSYour Name 		return tx_ops->dbr_tx_ops.direct_buf_rx_stop_buffer_poisoning(
6495*5113495bSYour Name 				pdev, 0);
6496*5113495bSYour Name }
6497*5113495bSYour Name 
6498*5113495bSYour Name /**
6499*5113495bSYour Name  * target_if_spectral_check_and_do_dbr_buff_debug() - Start/Stop Spectral buffer
6500*5113495bSYour Name  * debug based on the previous state
6501*5113495bSYour Name  * @pdev: Pointer to pdev object
6502*5113495bSYour Name  *
6503*5113495bSYour Name  * Return: QDF_STATUS of operation
6504*5113495bSYour Name  */
6505*5113495bSYour Name static QDF_STATUS
target_if_spectral_check_and_do_dbr_buff_debug(struct wlan_objmgr_pdev * pdev)6506*5113495bSYour Name target_if_spectral_check_and_do_dbr_buff_debug(struct wlan_objmgr_pdev *pdev)
6507*5113495bSYour Name {
6508*5113495bSYour Name 	struct target_if_spectral *spectral;
6509*5113495bSYour Name 
6510*5113495bSYour Name 	if (!pdev) {
6511*5113495bSYour Name 		spectral_err("pdev is NULL!");
6512*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
6513*5113495bSYour Name 	}
6514*5113495bSYour Name 
6515*5113495bSYour Name 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
6516*5113495bSYour Name 	if (!spectral) {
6517*5113495bSYour Name 		spectral_err("Spectal LMAC object is NULL");
6518*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
6519*5113495bSYour Name 	}
6520*5113495bSYour Name 
6521*5113495bSYour Name 	if (spectral->dbr_buff_debug)
6522*5113495bSYour Name 		return target_if_spectral_do_dbr_buff_debug(pdev, true);
6523*5113495bSYour Name 	else
6524*5113495bSYour Name 		return target_if_spectral_do_dbr_buff_debug(pdev, false);
6525*5113495bSYour Name }
6526*5113495bSYour Name 
6527*5113495bSYour Name /**
6528*5113495bSYour Name  * target_if_spectral_check_and_do_dbr_ring_debug() - Start/Stop Spectral ring
6529*5113495bSYour Name  * debug based on the previous state
6530*5113495bSYour Name  * @pdev: Pointer to pdev object
6531*5113495bSYour Name  *
6532*5113495bSYour Name  * Return: QDF_STATUS of operation
6533*5113495bSYour Name  */
6534*5113495bSYour Name static QDF_STATUS
target_if_spectral_check_and_do_dbr_ring_debug(struct wlan_objmgr_pdev * pdev)6535*5113495bSYour Name target_if_spectral_check_and_do_dbr_ring_debug(struct wlan_objmgr_pdev *pdev)
6536*5113495bSYour Name {
6537*5113495bSYour Name 	struct target_if_spectral *spectral;
6538*5113495bSYour Name 
6539*5113495bSYour Name 	if (!pdev) {
6540*5113495bSYour Name 		spectral_err("pdev is NULL!");
6541*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
6542*5113495bSYour Name 	}
6543*5113495bSYour Name 
6544*5113495bSYour Name 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
6545*5113495bSYour Name 	if (!spectral) {
6546*5113495bSYour Name 		spectral_err("Spectal LMAC object is NULL");
6547*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
6548*5113495bSYour Name 	}
6549*5113495bSYour Name 
6550*5113495bSYour Name 	if (spectral->dbr_ring_debug)
6551*5113495bSYour Name 		return target_if_spectral_do_dbr_ring_debug(pdev, true);
6552*5113495bSYour Name 	else
6553*5113495bSYour Name 		return target_if_spectral_do_dbr_ring_debug(pdev, false);
6554*5113495bSYour Name }
6555*5113495bSYour Name 
6556*5113495bSYour Name /**
6557*5113495bSYour Name  * target_if_spectral_set_dma_debug() - Set DMA debug for Spectral
6558*5113495bSYour Name  * @pdev: Pointer to pdev object
6559*5113495bSYour Name  * @dma_debug_type: Type of Spectral DMA debug i.e., ring or buffer debug
6560*5113495bSYour Name  * @debug_value: Value to be set for @dma_debug_type
6561*5113495bSYour Name  *
6562*5113495bSYour Name  * Set DMA debug for Spectral and start/stop Spectral DMA debug function
6563*5113495bSYour Name  * based on @debug_value
6564*5113495bSYour Name  *
6565*5113495bSYour Name  * Return: QDF_STATUS of operation
6566*5113495bSYour Name  */
6567*5113495bSYour Name static QDF_STATUS
target_if_spectral_set_dma_debug(struct wlan_objmgr_pdev * pdev,enum spectral_dma_debug dma_debug_type,bool debug_value)6568*5113495bSYour Name target_if_spectral_set_dma_debug(
6569*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev,
6570*5113495bSYour Name 	enum spectral_dma_debug dma_debug_type,
6571*5113495bSYour Name 	bool debug_value)
6572*5113495bSYour Name {
6573*5113495bSYour Name 	struct target_if_spectral_ops *p_sops;
6574*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
6575*5113495bSYour Name 	struct wlan_lmac_if_tx_ops *tx_ops;
6576*5113495bSYour Name 	struct target_if_spectral *spectral;
6577*5113495bSYour Name 
6578*5113495bSYour Name 	if (!pdev)
6579*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
6580*5113495bSYour Name 
6581*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
6582*5113495bSYour Name 	if (!psoc) {
6583*5113495bSYour Name 		spectral_err("psoc is null");
6584*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
6585*5113495bSYour Name 	}
6586*5113495bSYour Name 
6587*5113495bSYour Name 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
6588*5113495bSYour Name 	if (!tx_ops) {
6589*5113495bSYour Name 		spectral_err("tx_ops is NULL");
6590*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
6591*5113495bSYour Name 	}
6592*5113495bSYour Name 
6593*5113495bSYour Name 	if (!tx_ops->target_tx_ops.tgt_get_tgt_type) {
6594*5113495bSYour Name 		spectral_err("Unable to fetch target type");
6595*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
6596*5113495bSYour Name 	}
6597*5113495bSYour Name 
6598*5113495bSYour Name 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
6599*5113495bSYour Name 	if (!spectral) {
6600*5113495bSYour Name 		spectral_err("Spectal LMAC object is NULL");
6601*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
6602*5113495bSYour Name 	}
6603*5113495bSYour Name 
6604*5113495bSYour Name 	if (spectral->direct_dma_support) {
6605*5113495bSYour Name 		p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
6606*5113495bSYour Name 		if (p_sops->is_spectral_active(spectral,
6607*5113495bSYour Name 					       SPECTRAL_SCAN_MODE_NORMAL) ||
6608*5113495bSYour Name 		    p_sops->is_spectral_active(spectral,
6609*5113495bSYour Name 					       SPECTRAL_SCAN_MODE_AGILE)) {
6610*5113495bSYour Name 			spectral_err("Altering DBR debug config isn't allowed during an ongoing scan");
6611*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
6612*5113495bSYour Name 		}
6613*5113495bSYour Name 
6614*5113495bSYour Name 		switch (dma_debug_type) {
6615*5113495bSYour Name 		case SPECTRAL_DMA_RING_DEBUG:
6616*5113495bSYour Name 			target_if_spectral_do_dbr_ring_debug(pdev, debug_value);
6617*5113495bSYour Name 			break;
6618*5113495bSYour Name 
6619*5113495bSYour Name 		case SPECTRAL_DMA_BUFFER_DEBUG:
6620*5113495bSYour Name 			target_if_spectral_do_dbr_buff_debug(pdev, debug_value);
6621*5113495bSYour Name 			break;
6622*5113495bSYour Name 
6623*5113495bSYour Name 		default:
6624*5113495bSYour Name 			spectral_err("Unsupported DMA debug type : %d",
6625*5113495bSYour Name 				     dma_debug_type);
6626*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
6627*5113495bSYour Name 		}
6628*5113495bSYour Name 	}
6629*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
6630*5113495bSYour Name }
6631*5113495bSYour Name #endif /* DIRECT_BUF_RX_DEBUG */
6632*5113495bSYour Name 
6633*5113495bSYour Name /**
6634*5113495bSYour Name  * target_if_spectral_direct_dma_support() - Get Direct-DMA support
6635*5113495bSYour Name  * @pdev: Pointer to pdev object
6636*5113495bSYour Name  *
6637*5113495bSYour Name  * Return: Whether Direct-DMA is supported on this radio
6638*5113495bSYour Name  */
6639*5113495bSYour Name static bool
target_if_spectral_direct_dma_support(struct wlan_objmgr_pdev * pdev)6640*5113495bSYour Name target_if_spectral_direct_dma_support(struct wlan_objmgr_pdev *pdev)
6641*5113495bSYour Name {
6642*5113495bSYour Name 	struct target_if_spectral *spectral;
6643*5113495bSYour Name 
6644*5113495bSYour Name 	if (!pdev) {
6645*5113495bSYour Name 		spectral_err("pdev is NULL!");
6646*5113495bSYour Name 		return false;
6647*5113495bSYour Name 	}
6648*5113495bSYour Name 
6649*5113495bSYour Name 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
6650*5113495bSYour Name 	if (!spectral) {
6651*5113495bSYour Name 		spectral_err("Spectral LMAC object is NULL");
6652*5113495bSYour Name 		return false;
6653*5113495bSYour Name 	}
6654*5113495bSYour Name 
6655*5113495bSYour Name 	return spectral->direct_dma_support;
6656*5113495bSYour Name }
6657*5113495bSYour Name 
6658*5113495bSYour Name /**
6659*5113495bSYour Name  * target_if_set_debug_level() - Set debug level for Spectral
6660*5113495bSYour Name  * @pdev: Pointer to pdev object
6661*5113495bSYour Name  * @debug_level: Debug level
6662*5113495bSYour Name  *
6663*5113495bSYour Name  * API to set the debug level for Spectral
6664*5113495bSYour Name  *
6665*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
6666*5113495bSYour Name  */
6667*5113495bSYour Name QDF_STATUS
target_if_set_debug_level(struct wlan_objmgr_pdev * pdev,uint32_t debug_level)6668*5113495bSYour Name target_if_set_debug_level(struct wlan_objmgr_pdev *pdev, uint32_t debug_level)
6669*5113495bSYour Name {
6670*5113495bSYour Name 	spectral_debug_level = (DEBUG_SPECTRAL << debug_level);
6671*5113495bSYour Name 
6672*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
6673*5113495bSYour Name }
6674*5113495bSYour Name 
6675*5113495bSYour Name /**
6676*5113495bSYour Name  * target_if_get_debug_level() - Get debug level for Spectral
6677*5113495bSYour Name  * @pdev: Pointer to pdev object
6678*5113495bSYour Name  *
6679*5113495bSYour Name  * API to get the debug level for Spectral
6680*5113495bSYour Name  *
6681*5113495bSYour Name  * Return: Current debug level
6682*5113495bSYour Name  */
6683*5113495bSYour Name uint32_t
target_if_get_debug_level(struct wlan_objmgr_pdev * pdev)6684*5113495bSYour Name target_if_get_debug_level(struct wlan_objmgr_pdev *pdev)
6685*5113495bSYour Name {
6686*5113495bSYour Name 	return spectral_debug_level;
6687*5113495bSYour Name }
6688*5113495bSYour Name 
6689*5113495bSYour Name /**
6690*5113495bSYour Name  * target_if_get_spectral_capinfo() - Get Spectral capability information
6691*5113495bSYour Name  * @pdev: Pointer to pdev object
6692*5113495bSYour Name  * @scaps: Buffer into which data should be copied
6693*5113495bSYour Name  *
6694*5113495bSYour Name  * API to get the spectral capability information
6695*5113495bSYour Name  *
6696*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
6697*5113495bSYour Name  */
6698*5113495bSYour Name QDF_STATUS
target_if_get_spectral_capinfo(struct wlan_objmgr_pdev * pdev,struct spectral_caps * scaps)6699*5113495bSYour Name target_if_get_spectral_capinfo(struct wlan_objmgr_pdev *pdev,
6700*5113495bSYour Name 			       struct spectral_caps *scaps)
6701*5113495bSYour Name {
6702*5113495bSYour Name 	struct target_if_spectral *spectral = NULL;
6703*5113495bSYour Name 
6704*5113495bSYour Name 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
6705*5113495bSYour Name 	if (!spectral) {
6706*5113495bSYour Name 		spectral_err("SPECTRAL : Module doesn't exist");
6707*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
6708*5113495bSYour Name 	}
6709*5113495bSYour Name 
6710*5113495bSYour Name 	qdf_mem_copy(scaps, &spectral->capability,
6711*5113495bSYour Name 		     sizeof(struct spectral_caps));
6712*5113495bSYour Name 
6713*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
6714*5113495bSYour Name }
6715*5113495bSYour Name 
6716*5113495bSYour Name /**
6717*5113495bSYour Name  * target_if_get_spectral_diagstats() - Get Spectral diagnostic statistics
6718*5113495bSYour Name  * @pdev:  Pointer to pdev object
6719*5113495bSYour Name  * @stats: Buffer into which data should be copied
6720*5113495bSYour Name  *
6721*5113495bSYour Name  * API to get the spectral diagnostic statistics
6722*5113495bSYour Name  *
6723*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
6724*5113495bSYour Name  */
6725*5113495bSYour Name QDF_STATUS
target_if_get_spectral_diagstats(struct wlan_objmgr_pdev * pdev,struct spectral_diag_stats * stats)6726*5113495bSYour Name target_if_get_spectral_diagstats(struct wlan_objmgr_pdev *pdev,
6727*5113495bSYour Name 				 struct spectral_diag_stats *stats)
6728*5113495bSYour Name {
6729*5113495bSYour Name 	struct target_if_spectral *spectral = NULL;
6730*5113495bSYour Name 
6731*5113495bSYour Name 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
6732*5113495bSYour Name 	if (!spectral) {
6733*5113495bSYour Name 		spectral_err("SPECTRAL : Module doesn't exist");
6734*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
6735*5113495bSYour Name 	}
6736*5113495bSYour Name 
6737*5113495bSYour Name 	qdf_mem_copy(stats, &spectral->diag_stats,
6738*5113495bSYour Name 		     sizeof(struct spectral_diag_stats));
6739*5113495bSYour Name 
6740*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
6741*5113495bSYour Name }
6742*5113495bSYour Name 
6743*5113495bSYour Name /**
6744*5113495bSYour Name  * target_if_register_spectral_wmi_ops() - Register Spectral WMI operations
6745*5113495bSYour Name  * @psoc: Pointer to psoc object
6746*5113495bSYour Name  * @wmi_ops: Pointer to the structure having Spectral WMI operations
6747*5113495bSYour Name  *
6748*5113495bSYour Name  * API for registering Spectral WMI operations in
6749*5113495bSYour Name  * spectral internal data structure
6750*5113495bSYour Name  *
6751*5113495bSYour Name  * Return: QDF_STATUS
6752*5113495bSYour Name  */
6753*5113495bSYour Name static QDF_STATUS
target_if_register_spectral_wmi_ops(struct wlan_objmgr_psoc * psoc,struct spectral_wmi_ops * wmi_ops)6754*5113495bSYour Name target_if_register_spectral_wmi_ops(struct wlan_objmgr_psoc *psoc,
6755*5113495bSYour Name 				    struct spectral_wmi_ops *wmi_ops)
6756*5113495bSYour Name {
6757*5113495bSYour Name 	struct target_if_psoc_spectral *psoc_spectral;
6758*5113495bSYour Name 
6759*5113495bSYour Name 	psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
6760*5113495bSYour Name 	if (!psoc_spectral) {
6761*5113495bSYour Name 		spectral_err("Spectral LMAC object is null");
6762*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
6763*5113495bSYour Name 	}
6764*5113495bSYour Name 
6765*5113495bSYour Name 	psoc_spectral->wmi_ops = *wmi_ops;
6766*5113495bSYour Name 
6767*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
6768*5113495bSYour Name }
6769*5113495bSYour Name 
6770*5113495bSYour Name /**
6771*5113495bSYour Name  * target_if_register_spectral_tgt_ops() - Register Spectral target operations
6772*5113495bSYour Name  * @psoc: Pointer to psoc object
6773*5113495bSYour Name  * @tgt_ops: Pointer to the structure having Spectral target operations
6774*5113495bSYour Name  *
6775*5113495bSYour Name  * API for registering Spectral target operations in
6776*5113495bSYour Name  * spectral internal data structure
6777*5113495bSYour Name  *
6778*5113495bSYour Name  * Return: QDF_STATUS
6779*5113495bSYour Name  */
6780*5113495bSYour Name static QDF_STATUS
target_if_register_spectral_tgt_ops(struct wlan_objmgr_psoc * psoc,struct spectral_tgt_ops * tgt_ops)6781*5113495bSYour Name target_if_register_spectral_tgt_ops(struct wlan_objmgr_psoc *psoc,
6782*5113495bSYour Name 				    struct spectral_tgt_ops *tgt_ops)
6783*5113495bSYour Name {
6784*5113495bSYour Name 	if (!psoc) {
6785*5113495bSYour Name 		spectral_err("psoc is null");
6786*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
6787*5113495bSYour Name 	}
6788*5113495bSYour Name 
6789*5113495bSYour Name 	ops_tgt = *tgt_ops;
6790*5113495bSYour Name 
6791*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
6792*5113495bSYour Name }
6793*5113495bSYour Name 
6794*5113495bSYour Name /**
6795*5113495bSYour Name  * target_if_register_netlink_cb() - Register Netlink callbacks
6796*5113495bSYour Name  * @pdev: Pointer to pdev object
6797*5113495bSYour Name  * @nl_cb: Netlink callbacks to register
6798*5113495bSYour Name  *
6799*5113495bSYour Name  * Return: void
6800*5113495bSYour Name  */
6801*5113495bSYour Name static void
target_if_register_netlink_cb(struct wlan_objmgr_pdev * pdev,struct spectral_nl_cb * nl_cb)6802*5113495bSYour Name target_if_register_netlink_cb(
6803*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev,
6804*5113495bSYour Name 	struct spectral_nl_cb *nl_cb)
6805*5113495bSYour Name {
6806*5113495bSYour Name 	struct target_if_spectral *spectral = NULL;
6807*5113495bSYour Name 
6808*5113495bSYour Name 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
6809*5113495bSYour Name 
6810*5113495bSYour Name 	if (!spectral) {
6811*5113495bSYour Name 		spectral_err("SPECTRAL : Module doesn't exist");
6812*5113495bSYour Name 		return;
6813*5113495bSYour Name 	}
6814*5113495bSYour Name 
6815*5113495bSYour Name 	qdf_mem_copy(&spectral->nl_cb, nl_cb, sizeof(struct spectral_nl_cb));
6816*5113495bSYour Name 
6817*5113495bSYour Name 	if (spectral->use_nl_bcast)
6818*5113495bSYour Name 		spectral->send_phy_data = spectral->nl_cb.send_nl_bcast;
6819*5113495bSYour Name 	else
6820*5113495bSYour Name 		spectral->send_phy_data = spectral->nl_cb.send_nl_unicast;
6821*5113495bSYour Name }
6822*5113495bSYour Name 
6823*5113495bSYour Name /**
6824*5113495bSYour Name  * target_if_use_nl_bcast() - Get whether to use broadcast/unicast while sending
6825*5113495bSYour Name  * Netlink messages to the application layer
6826*5113495bSYour Name  * @pdev: Pointer to pdev object
6827*5113495bSYour Name  *
6828*5113495bSYour Name  * Return: true for broadcast, false for unicast
6829*5113495bSYour Name  */
6830*5113495bSYour Name static bool
target_if_use_nl_bcast(struct wlan_objmgr_pdev * pdev)6831*5113495bSYour Name target_if_use_nl_bcast(struct wlan_objmgr_pdev *pdev)
6832*5113495bSYour Name {
6833*5113495bSYour Name 	struct target_if_spectral *spectral = NULL;
6834*5113495bSYour Name 
6835*5113495bSYour Name 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
6836*5113495bSYour Name 
6837*5113495bSYour Name 	if (!spectral) {
6838*5113495bSYour Name 		spectral_err("SPECTRAL : Module doesn't exist");
6839*5113495bSYour Name 		return false;
6840*5113495bSYour Name 	}
6841*5113495bSYour Name 
6842*5113495bSYour Name 	return spectral->use_nl_bcast;
6843*5113495bSYour Name }
6844*5113495bSYour Name 
6845*5113495bSYour Name /**
6846*5113495bSYour Name  * target_if_deregister_netlink_cb() - De-register Netlink callbacks
6847*5113495bSYour Name  * @pdev: Pointer to pdev object
6848*5113495bSYour Name  *
6849*5113495bSYour Name  * Return: void
6850*5113495bSYour Name  */
6851*5113495bSYour Name static void
target_if_deregister_netlink_cb(struct wlan_objmgr_pdev * pdev)6852*5113495bSYour Name target_if_deregister_netlink_cb(struct wlan_objmgr_pdev *pdev)
6853*5113495bSYour Name {
6854*5113495bSYour Name 	struct target_if_spectral *spectral = NULL;
6855*5113495bSYour Name 
6856*5113495bSYour Name 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
6857*5113495bSYour Name 	if (!spectral) {
6858*5113495bSYour Name 		spectral_err("SPECTRAL : Module doesn't exist");
6859*5113495bSYour Name 		return;
6860*5113495bSYour Name 	}
6861*5113495bSYour Name 
6862*5113495bSYour Name 	qdf_mem_zero(&spectral->nl_cb, sizeof(struct spectral_nl_cb));
6863*5113495bSYour Name }
6864*5113495bSYour Name 
6865*5113495bSYour Name static int
target_if_process_spectral_report(struct wlan_objmgr_pdev * pdev,void * payload)6866*5113495bSYour Name target_if_process_spectral_report(struct wlan_objmgr_pdev *pdev,
6867*5113495bSYour Name 				  void *payload)
6868*5113495bSYour Name {
6869*5113495bSYour Name 	struct target_if_spectral *spectral = NULL;
6870*5113495bSYour Name 	struct target_if_spectral_ops *p_sops = NULL;
6871*5113495bSYour Name 
6872*5113495bSYour Name 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
6873*5113495bSYour Name 	if (!spectral) {
6874*5113495bSYour Name 		spectral_err("SPECTRAL : Module doesn't exist");
6875*5113495bSYour Name 		return -EPERM;
6876*5113495bSYour Name 	}
6877*5113495bSYour Name 
6878*5113495bSYour Name 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
6879*5113495bSYour Name 
6880*5113495bSYour Name 	if (!p_sops) {
6881*5113495bSYour Name 		spectral_err("p_sops is null");
6882*5113495bSYour Name 		return -EPERM;
6883*5113495bSYour Name 	}
6884*5113495bSYour Name 
6885*5113495bSYour Name 	return p_sops->process_spectral_report(pdev, payload);
6886*5113495bSYour Name }
6887*5113495bSYour Name 
6888*5113495bSYour Name #ifdef DIRECT_BUF_RX_DEBUG
6889*5113495bSYour Name static inline void
target_if_sptrl_debug_register_tx_ops(struct wlan_lmac_if_tx_ops * tx_ops)6890*5113495bSYour Name target_if_sptrl_debug_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
6891*5113495bSYour Name {
6892*5113495bSYour Name 	if (!tx_ops) {
6893*5113495bSYour Name 		spectral_err("tx_ops is NULL");
6894*5113495bSYour Name 		return;
6895*5113495bSYour Name 	}
6896*5113495bSYour Name 
6897*5113495bSYour Name 	tx_ops->sptrl_tx_ops.sptrlto_set_dma_debug =
6898*5113495bSYour Name 		target_if_spectral_set_dma_debug;
6899*5113495bSYour Name 	tx_ops->sptrl_tx_ops.sptrlto_check_and_do_dbr_ring_debug =
6900*5113495bSYour Name 		target_if_spectral_check_and_do_dbr_ring_debug;
6901*5113495bSYour Name 	tx_ops->sptrl_tx_ops.sptrlto_check_and_do_dbr_buff_debug =
6902*5113495bSYour Name 		target_if_spectral_check_and_do_dbr_buff_debug;
6903*5113495bSYour Name }
6904*5113495bSYour Name #else
6905*5113495bSYour Name static inline void
target_if_sptrl_debug_register_tx_ops(struct wlan_lmac_if_tx_ops * tx_ops)6906*5113495bSYour Name target_if_sptrl_debug_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
6907*5113495bSYour Name {
6908*5113495bSYour Name }
6909*5113495bSYour Name #endif
6910*5113495bSYour Name 
6911*5113495bSYour Name #if defined(WLAN_CONV_SPECTRAL_ENABLE) && defined(SPECTRAL_MODULIZED_ENABLE)
6912*5113495bSYour Name /**
6913*5113495bSYour Name  * target_if_spectral_wmi_unified_register_event_handler() - Wrapper function to
6914*5113495bSYour Name  * register WMI event handler
6915*5113495bSYour Name  * @psoc: Pointer to psoc object
6916*5113495bSYour Name  * @event_id: Event id
6917*5113495bSYour Name  * @handler_func: Handler function
6918*5113495bSYour Name  * @rx_ctx: Context of WMI event processing
6919*5113495bSYour Name  *
6920*5113495bSYour Name  * Wrapper function to register WMI event handler
6921*5113495bSYour Name  *
6922*5113495bSYour Name  * Return: 0 for success else failure
6923*5113495bSYour Name  */
6924*5113495bSYour Name static int
target_if_spectral_wmi_unified_register_event_handler(struct wlan_objmgr_psoc * psoc,wmi_conv_event_id event_id,wmi_unified_event_handler handler_func,uint8_t rx_ctx)6925*5113495bSYour Name target_if_spectral_wmi_unified_register_event_handler(
6926*5113495bSYour Name 				struct wlan_objmgr_psoc *psoc,
6927*5113495bSYour Name 				wmi_conv_event_id event_id,
6928*5113495bSYour Name 				wmi_unified_event_handler handler_func,
6929*5113495bSYour Name 				uint8_t rx_ctx)
6930*5113495bSYour Name {
6931*5113495bSYour Name 	wmi_unified_t wmi_handle;
6932*5113495bSYour Name 	struct target_if_psoc_spectral *psoc_spectral;
6933*5113495bSYour Name 	QDF_STATUS ret;
6934*5113495bSYour Name 
6935*5113495bSYour Name 	if (!psoc) {
6936*5113495bSYour Name 		spectral_err("psoc is null");
6937*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
6938*5113495bSYour Name 	}
6939*5113495bSYour Name 
6940*5113495bSYour Name 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
6941*5113495bSYour Name 	if (!wmi_handle) {
6942*5113495bSYour Name 		spectral_err("WMI handle is null");
6943*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
6944*5113495bSYour Name 	}
6945*5113495bSYour Name 
6946*5113495bSYour Name 	psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
6947*5113495bSYour Name 	if (!psoc_spectral) {
6948*5113495bSYour Name 		spectral_err("spectral object is null");
6949*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
6950*5113495bSYour Name 	}
6951*5113495bSYour Name 
6952*5113495bSYour Name 	ret = psoc_spectral->wmi_ops.wmi_unified_register_event_handler(
6953*5113495bSYour Name 			wmi_handle, event_id, handler_func, rx_ctx);
6954*5113495bSYour Name 
6955*5113495bSYour Name 	return qdf_status_to_os_return(ret);
6956*5113495bSYour Name }
6957*5113495bSYour Name 
6958*5113495bSYour Name /**
6959*5113495bSYour Name  * target_if_spectral_wmi_unified_unregister_event_handler() - Wrapper function
6960*5113495bSYour Name  * to unregister WMI event handler
6961*5113495bSYour Name  * @psoc: Pointer to psoc object
6962*5113495bSYour Name  * @event_id: Event id
6963*5113495bSYour Name  *
6964*5113495bSYour Name  * Wrapper function to unregister WMI event handler
6965*5113495bSYour Name  *
6966*5113495bSYour Name  * Return: 0 for success else failure
6967*5113495bSYour Name  */
6968*5113495bSYour Name static int
target_if_spectral_wmi_unified_unregister_event_handler(struct wlan_objmgr_psoc * psoc,wmi_conv_event_id event_id)6969*5113495bSYour Name target_if_spectral_wmi_unified_unregister_event_handler(
6970*5113495bSYour Name 				struct wlan_objmgr_psoc *psoc,
6971*5113495bSYour Name 				wmi_conv_event_id event_id)
6972*5113495bSYour Name {
6973*5113495bSYour Name 	wmi_unified_t wmi_handle;
6974*5113495bSYour Name 	struct target_if_psoc_spectral *psoc_spectral;
6975*5113495bSYour Name 	QDF_STATUS ret;
6976*5113495bSYour Name 
6977*5113495bSYour Name 	if (!psoc) {
6978*5113495bSYour Name 		spectral_err("psoc is null");
6979*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
6980*5113495bSYour Name 	}
6981*5113495bSYour Name 
6982*5113495bSYour Name 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
6983*5113495bSYour Name 	if (!wmi_handle) {
6984*5113495bSYour Name 		spectral_err("WMI handle is null");
6985*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
6986*5113495bSYour Name 	}
6987*5113495bSYour Name 
6988*5113495bSYour Name 	psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
6989*5113495bSYour Name 	if (!psoc_spectral) {
6990*5113495bSYour Name 		spectral_err("spectral object is null");
6991*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
6992*5113495bSYour Name 	}
6993*5113495bSYour Name 
6994*5113495bSYour Name 	ret = psoc_spectral->wmi_ops.wmi_unified_unregister_event_handler(
6995*5113495bSYour Name 					wmi_handle, event_id);
6996*5113495bSYour Name 
6997*5113495bSYour Name 	return qdf_status_to_os_return(ret);
6998*5113495bSYour Name }
6999*5113495bSYour Name 
7000*5113495bSYour Name /**
7001*5113495bSYour Name  * target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param() - Wrapper
7002*5113495bSYour Name  * function to extract fixed parameters from start scan response event
7003*5113495bSYour Name  * @psoc: Pointer to psoc object
7004*5113495bSYour Name  * @evt_buf: Event buffer
7005*5113495bSYour Name  * @param: Start scan response parameters
7006*5113495bSYour Name  *
7007*5113495bSYour Name  * Wrapper function to extract fixed parameters from start scan response event
7008*5113495bSYour Name  *
7009*5113495bSYour Name  * Return: QDF_STATUS
7010*5113495bSYour Name  */
7011*5113495bSYour Name static QDF_STATUS
target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param(struct wlan_objmgr_psoc * psoc,uint8_t * evt_buf,struct spectral_startscan_resp_params * param)7012*5113495bSYour Name target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param(
7013*5113495bSYour Name 			struct wlan_objmgr_psoc *psoc,
7014*5113495bSYour Name 			uint8_t *evt_buf,
7015*5113495bSYour Name 			struct spectral_startscan_resp_params *param)
7016*5113495bSYour Name {
7017*5113495bSYour Name 	wmi_unified_t wmi_handle;
7018*5113495bSYour Name 	struct target_if_psoc_spectral *psoc_spectral;
7019*5113495bSYour Name 
7020*5113495bSYour Name 	if (!psoc) {
7021*5113495bSYour Name 		spectral_err("psoc is null");
7022*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
7023*5113495bSYour Name 	}
7024*5113495bSYour Name 
7025*5113495bSYour Name 	if (!evt_buf) {
7026*5113495bSYour Name 		spectral_err("WMI event buffer is null");
7027*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
7028*5113495bSYour Name 	}
7029*5113495bSYour Name 
7030*5113495bSYour Name 	if (!param) {
7031*5113495bSYour Name 		spectral_err("Spectral startscan response parameters is null");
7032*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
7033*5113495bSYour Name 	}
7034*5113495bSYour Name 
7035*5113495bSYour Name 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7036*5113495bSYour Name 	if (!wmi_handle) {
7037*5113495bSYour Name 		spectral_err("WMI handle is null");
7038*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
7039*5113495bSYour Name 	}
7040*5113495bSYour Name 
7041*5113495bSYour Name 	psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
7042*5113495bSYour Name 	if (!psoc_spectral) {
7043*5113495bSYour Name 		spectral_err("spectral object is null");
7044*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
7045*5113495bSYour Name 	}
7046*5113495bSYour Name 
7047*5113495bSYour Name 	return psoc_spectral->wmi_ops.wmi_extract_pdev_sscan_fw_cmd_fixed_param(
7048*5113495bSYour Name 			wmi_handle, evt_buf, param);
7049*5113495bSYour Name }
7050*5113495bSYour Name 
7051*5113495bSYour Name /**
7052*5113495bSYour Name  * target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index() - Wrapper
7053*5113495bSYour Name  * function to extract start and end indices of primary 80 MHz, 5 MHz and
7054*5113495bSYour Name  * secondary 80 MHz FFT bins
7055*5113495bSYour Name  * @psoc: Pointer to psoc object
7056*5113495bSYour Name  * @evt_buf: Event buffer
7057*5113495bSYour Name  * @param: FFT bin start and end indices
7058*5113495bSYour Name  *
7059*5113495bSYour Name  * Wrapper function to extract start and end indices of primary 80 MHz, 5 MHz
7060*5113495bSYour Name  * and secondary 80 MHz FFT bins
7061*5113495bSYour Name  *
7062*5113495bSYour Name  * Return: QDF_STATUS
7063*5113495bSYour Name  */
7064*5113495bSYour Name static QDF_STATUS
target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index(struct wlan_objmgr_psoc * psoc,uint8_t * evt_buf,struct spectral_fft_bin_markers_160_165mhz * param)7065*5113495bSYour Name target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index(
7066*5113495bSYour Name 			struct wlan_objmgr_psoc *psoc,
7067*5113495bSYour Name 			uint8_t *evt_buf,
7068*5113495bSYour Name 			struct spectral_fft_bin_markers_160_165mhz *param)
7069*5113495bSYour Name {
7070*5113495bSYour Name 	wmi_unified_t wmi_handle;
7071*5113495bSYour Name 	struct target_if_psoc_spectral *psoc_spectral;
7072*5113495bSYour Name 
7073*5113495bSYour Name 	if (!psoc) {
7074*5113495bSYour Name 		spectral_err("psoc is null");
7075*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
7076*5113495bSYour Name 	}
7077*5113495bSYour Name 
7078*5113495bSYour Name 	if (!evt_buf) {
7079*5113495bSYour Name 		spectral_err("WMI event buffer is null");
7080*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
7081*5113495bSYour Name 	}
7082*5113495bSYour Name 
7083*5113495bSYour Name 	if (!param) {
7084*5113495bSYour Name 		spectral_err("Spectral FFT bin markers is null");
7085*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
7086*5113495bSYour Name 	}
7087*5113495bSYour Name 
7088*5113495bSYour Name 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7089*5113495bSYour Name 	if (!wmi_handle) {
7090*5113495bSYour Name 		spectral_err("WMI handle is null");
7091*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
7092*5113495bSYour Name 	}
7093*5113495bSYour Name 
7094*5113495bSYour Name 	psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
7095*5113495bSYour Name 	if (!psoc_spectral) {
7096*5113495bSYour Name 		spectral_err("spectral object is null");
7097*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
7098*5113495bSYour Name 	}
7099*5113495bSYour Name 
7100*5113495bSYour Name 	return psoc_spectral->wmi_ops.wmi_extract_pdev_sscan_fft_bin_index(
7101*5113495bSYour Name 			wmi_handle, evt_buf, param);
7102*5113495bSYour Name }
7103*5113495bSYour Name 
7104*5113495bSYour Name /**
7105*5113495bSYour Name  * target_if_spectral_get_psoc_from_scn_handle() - Wrapper function to get psoc
7106*5113495bSYour Name  * object from scn handle
7107*5113495bSYour Name  * @scn: scn handle
7108*5113495bSYour Name  *
7109*5113495bSYour Name  * Wrapper function to get psoc object from scn handle
7110*5113495bSYour Name  *
7111*5113495bSYour Name  * Return: Pointer to psoc object
7112*5113495bSYour Name  */
7113*5113495bSYour Name static struct wlan_objmgr_psoc *
target_if_spectral_get_psoc_from_scn_handle(ol_scn_t scn)7114*5113495bSYour Name target_if_spectral_get_psoc_from_scn_handle(ol_scn_t scn)
7115*5113495bSYour Name {
7116*5113495bSYour Name 	if (!scn) {
7117*5113495bSYour Name 		spectral_err("scn is null");
7118*5113495bSYour Name 		return NULL;
7119*5113495bSYour Name 	}
7120*5113495bSYour Name 
7121*5113495bSYour Name 	return ops_tgt.tgt_get_psoc_from_scn_hdl(scn);
7122*5113495bSYour Name }
7123*5113495bSYour Name 
7124*5113495bSYour Name /**
7125*5113495bSYour Name  * target_if_extract_pdev_spectral_session_chan_info() - Wrapper
7126*5113495bSYour Name  * function to extract channel information for a spectral scan session
7127*5113495bSYour Name  * @psoc: Pointer to psoc object
7128*5113495bSYour Name  * @evt_buf: Event buffer
7129*5113495bSYour Name  * @chan_info: Spectral session channel information data structure to be filled
7130*5113495bSYour Name  * by this API
7131*5113495bSYour Name  *
7132*5113495bSYour Name  * Return: QDF_STATUS of operation
7133*5113495bSYour Name  */
7134*5113495bSYour Name static QDF_STATUS
target_if_extract_pdev_spectral_session_chan_info(struct wlan_objmgr_psoc * psoc,void * evt_buf,struct spectral_session_chan_info * chan_info)7135*5113495bSYour Name target_if_extract_pdev_spectral_session_chan_info(
7136*5113495bSYour Name 			struct wlan_objmgr_psoc *psoc,
7137*5113495bSYour Name 			void *evt_buf,
7138*5113495bSYour Name 			struct spectral_session_chan_info *chan_info)
7139*5113495bSYour Name {
7140*5113495bSYour Name 	wmi_unified_t wmi_handle;
7141*5113495bSYour Name 	struct target_if_psoc_spectral *psoc_spectral;
7142*5113495bSYour Name 
7143*5113495bSYour Name 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7144*5113495bSYour Name 	if (!wmi_handle) {
7145*5113495bSYour Name 		spectral_err("WMI handle is null");
7146*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
7147*5113495bSYour Name 	}
7148*5113495bSYour Name 
7149*5113495bSYour Name 	psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
7150*5113495bSYour Name 	if (!psoc_spectral) {
7151*5113495bSYour Name 		spectral_err("spectral object is null");
7152*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
7153*5113495bSYour Name 	}
7154*5113495bSYour Name 
7155*5113495bSYour Name 	return psoc_spectral->wmi_ops.extract_pdev_spectral_session_chan_info(
7156*5113495bSYour Name 			wmi_handle, evt_buf, chan_info);
7157*5113495bSYour Name }
7158*5113495bSYour Name 
7159*5113495bSYour Name /**
7160*5113495bSYour Name  * target_if_extract_pdev_spectral_session_detector_info() - Wrapper
7161*5113495bSYour Name  * function to extract detector information for a spectral scan session
7162*5113495bSYour Name  * @psoc: Pointer to psoc object
7163*5113495bSYour Name  * @evt_buf: Event buffer
7164*5113495bSYour Name  * @det_info: Spectral session detector information data structure to be filled
7165*5113495bSYour Name  * by this API
7166*5113495bSYour Name  * @det_info_idx: index in the array of spectral scan detector info TLVs
7167*5113495bSYour Name  *
7168*5113495bSYour Name  * Return: QDF_STATUS of operation
7169*5113495bSYour Name  */
7170*5113495bSYour Name static QDF_STATUS
target_if_extract_pdev_spectral_session_detector_info(struct wlan_objmgr_psoc * psoc,void * evt_buf,struct spectral_session_det_info * det_info,uint8_t det_info_idx)7171*5113495bSYour Name target_if_extract_pdev_spectral_session_detector_info(
7172*5113495bSYour Name 			struct wlan_objmgr_psoc *psoc, void *evt_buf,
7173*5113495bSYour Name 			struct spectral_session_det_info *det_info,
7174*5113495bSYour Name 			uint8_t det_info_idx)
7175*5113495bSYour Name {
7176*5113495bSYour Name 	wmi_unified_t wmi_handle;
7177*5113495bSYour Name 	struct target_if_psoc_spectral *psoc_spectral;
7178*5113495bSYour Name 
7179*5113495bSYour Name 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7180*5113495bSYour Name 	if (!wmi_handle) {
7181*5113495bSYour Name 		spectral_err("WMI handle is null");
7182*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
7183*5113495bSYour Name 	}
7184*5113495bSYour Name 
7185*5113495bSYour Name 	psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
7186*5113495bSYour Name 	if (!psoc_spectral) {
7187*5113495bSYour Name 		spectral_err("spectral object is null");
7188*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
7189*5113495bSYour Name 	}
7190*5113495bSYour Name 
7191*5113495bSYour Name 	return psoc_spectral->wmi_ops.
7192*5113495bSYour Name 			extract_pdev_spectral_session_detector_info(
7193*5113495bSYour Name 				wmi_handle, evt_buf, det_info, det_info_idx);
7194*5113495bSYour Name }
7195*5113495bSYour Name 
7196*5113495bSYour Name /**
7197*5113495bSYour Name  * target_if_wmi_extract_spectral_caps_fixed_param() - Wrapper function to
7198*5113495bSYour Name  * extract fixed params from Spectral capabilities WMI event
7199*5113495bSYour Name  * @psoc: Pointer to psoc object
7200*5113495bSYour Name  * @evt_buf: Event buffer
7201*5113495bSYour Name  * @param: Spectral capabilities event parameters data structure to be filled
7202*5113495bSYour Name  * by this API
7203*5113495bSYour Name  *
7204*5113495bSYour Name  * Return: QDF_STATUS of operation
7205*5113495bSYour Name  */
7206*5113495bSYour Name QDF_STATUS
target_if_wmi_extract_spectral_caps_fixed_param(struct wlan_objmgr_psoc * psoc,uint8_t * evt_buf,struct spectral_capabilities_event_params * param)7207*5113495bSYour Name target_if_wmi_extract_spectral_caps_fixed_param(
7208*5113495bSYour Name 			struct wlan_objmgr_psoc *psoc,
7209*5113495bSYour Name 			uint8_t *evt_buf,
7210*5113495bSYour Name 			struct spectral_capabilities_event_params *param)
7211*5113495bSYour Name {
7212*5113495bSYour Name 	struct target_if_psoc_spectral *psoc_spectral;
7213*5113495bSYour Name 	wmi_unified_t wmi_handle;
7214*5113495bSYour Name 
7215*5113495bSYour Name 	if (!psoc) {
7216*5113495bSYour Name 		spectral_err("psoc is null");
7217*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
7218*5113495bSYour Name 	}
7219*5113495bSYour Name 
7220*5113495bSYour Name 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7221*5113495bSYour Name 	if (!wmi_handle) {
7222*5113495bSYour Name 		spectral_err("WMI handle is null");
7223*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
7224*5113495bSYour Name 	}
7225*5113495bSYour Name 
7226*5113495bSYour Name 	psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
7227*5113495bSYour Name 	if (!psoc_spectral) {
7228*5113495bSYour Name 		spectral_err("spectral object is null");
7229*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
7230*5113495bSYour Name 	}
7231*5113495bSYour Name 
7232*5113495bSYour Name 	return psoc_spectral->wmi_ops.extract_spectral_caps_fixed_param(
7233*5113495bSYour Name 			wmi_handle, evt_buf, param);
7234*5113495bSYour Name }
7235*5113495bSYour Name 
7236*5113495bSYour Name /**
7237*5113495bSYour Name  * target_if_wmi_extract_spectral_scan_bw_caps() - Wrapper function to
7238*5113495bSYour Name  * extract bandwidth capabilities from Spectral capabilities WMI event
7239*5113495bSYour Name  * @psoc: Pointer to psoc object
7240*5113495bSYour Name  * @evt_buf: Event buffer
7241*5113495bSYour Name  * @bw_caps: Data structure to be filled by this API after extraction
7242*5113495bSYour Name  *
7243*5113495bSYour Name  * Return: QDF_STATUS of operation
7244*5113495bSYour Name  */
7245*5113495bSYour Name QDF_STATUS
target_if_wmi_extract_spectral_scan_bw_caps(struct wlan_objmgr_psoc * psoc,uint8_t * evt_buf,struct spectral_scan_bw_capabilities * bw_caps)7246*5113495bSYour Name target_if_wmi_extract_spectral_scan_bw_caps(
7247*5113495bSYour Name 			struct wlan_objmgr_psoc *psoc,
7248*5113495bSYour Name 			uint8_t *evt_buf,
7249*5113495bSYour Name 			struct spectral_scan_bw_capabilities *bw_caps)
7250*5113495bSYour Name {
7251*5113495bSYour Name 	struct target_if_psoc_spectral *psoc_spectral;
7252*5113495bSYour Name 	wmi_unified_t wmi_handle;
7253*5113495bSYour Name 
7254*5113495bSYour Name 	if (!psoc) {
7255*5113495bSYour Name 		spectral_err("psoc is null");
7256*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
7257*5113495bSYour Name 	}
7258*5113495bSYour Name 
7259*5113495bSYour Name 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7260*5113495bSYour Name 	if (!wmi_handle) {
7261*5113495bSYour Name 		spectral_err("WMI handle is null");
7262*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
7263*5113495bSYour Name 	}
7264*5113495bSYour Name 
7265*5113495bSYour Name 	psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
7266*5113495bSYour Name 	if (!psoc_spectral) {
7267*5113495bSYour Name 		spectral_err("spectral object is null");
7268*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
7269*5113495bSYour Name 	}
7270*5113495bSYour Name 
7271*5113495bSYour Name 	return psoc_spectral->wmi_ops.extract_spectral_scan_bw_caps(
7272*5113495bSYour Name 			wmi_handle, evt_buf, bw_caps);
7273*5113495bSYour Name }
7274*5113495bSYour Name 
7275*5113495bSYour Name /**
7276*5113495bSYour Name  * target_if_wmi_extract_spectral_fft_size_caps() - Wrapper function to
7277*5113495bSYour Name  * extract fft size capabilities from Spectral capabilities WMI event
7278*5113495bSYour Name  * @psoc: Pointer to psoc object
7279*5113495bSYour Name  * @evt_buf: Event buffer
7280*5113495bSYour Name  * @fft_size_caps: Data structure to be filled by this API after extraction
7281*5113495bSYour Name  *
7282*5113495bSYour Name  * Return: QDF_STATUS of operation
7283*5113495bSYour Name  */
7284*5113495bSYour Name QDF_STATUS
target_if_wmi_extract_spectral_fft_size_caps(struct wlan_objmgr_psoc * psoc,uint8_t * evt_buf,struct spectral_fft_size_capabilities * fft_size_caps)7285*5113495bSYour Name target_if_wmi_extract_spectral_fft_size_caps(
7286*5113495bSYour Name 			struct wlan_objmgr_psoc *psoc,
7287*5113495bSYour Name 			uint8_t *evt_buf,
7288*5113495bSYour Name 			struct spectral_fft_size_capabilities *fft_size_caps)
7289*5113495bSYour Name {
7290*5113495bSYour Name 	struct target_if_psoc_spectral *psoc_spectral;
7291*5113495bSYour Name 	wmi_unified_t wmi_handle;
7292*5113495bSYour Name 
7293*5113495bSYour Name 	if (!psoc) {
7294*5113495bSYour Name 		spectral_err("psoc is null");
7295*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
7296*5113495bSYour Name 	}
7297*5113495bSYour Name 
7298*5113495bSYour Name 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7299*5113495bSYour Name 	if (!wmi_handle) {
7300*5113495bSYour Name 		spectral_err("WMI handle is null");
7301*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
7302*5113495bSYour Name 	}
7303*5113495bSYour Name 
7304*5113495bSYour Name 	psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
7305*5113495bSYour Name 	if (!psoc_spectral) {
7306*5113495bSYour Name 		spectral_err("spectral object is null");
7307*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
7308*5113495bSYour Name 	}
7309*5113495bSYour Name 
7310*5113495bSYour Name 	return psoc_spectral->wmi_ops.extract_spectral_fft_size_caps(
7311*5113495bSYour Name 			wmi_handle, evt_buf, fft_size_caps);
7312*5113495bSYour Name }
7313*5113495bSYour Name #else
7314*5113495bSYour Name /**
7315*5113495bSYour Name  * target_if_spectral_wmi_unified_register_event_handler() - Wrapper function to
7316*5113495bSYour Name  * register WMI event handler
7317*5113495bSYour Name  * @psoc: Pointer to psoc object
7318*5113495bSYour Name  * @event_id: Event id
7319*5113495bSYour Name  * @handler_func: Handler function
7320*5113495bSYour Name  * @rx_ctx: Context of WMI event processing
7321*5113495bSYour Name  *
7322*5113495bSYour Name  * Wrapper function to register WMI event handler
7323*5113495bSYour Name  *
7324*5113495bSYour Name  * Return: 0 for success else failure
7325*5113495bSYour Name  */
7326*5113495bSYour Name static int
target_if_spectral_wmi_unified_register_event_handler(struct wlan_objmgr_psoc * psoc,wmi_conv_event_id event_id,wmi_unified_event_handler handler_func,uint8_t rx_ctx)7327*5113495bSYour Name target_if_spectral_wmi_unified_register_event_handler(
7328*5113495bSYour Name 				struct wlan_objmgr_psoc *psoc,
7329*5113495bSYour Name 				wmi_conv_event_id event_id,
7330*5113495bSYour Name 				wmi_unified_event_handler handler_func,
7331*5113495bSYour Name 				uint8_t rx_ctx)
7332*5113495bSYour Name {
7333*5113495bSYour Name 	wmi_unified_t wmi_handle;
7334*5113495bSYour Name 	QDF_STATUS ret;
7335*5113495bSYour Name 
7336*5113495bSYour Name 	if (!psoc) {
7337*5113495bSYour Name 		spectral_err("psoc is null");
7338*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
7339*5113495bSYour Name 	}
7340*5113495bSYour Name 
7341*5113495bSYour Name 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7342*5113495bSYour Name 	if (!wmi_handle) {
7343*5113495bSYour Name 		spectral_err("WMI handle is null");
7344*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
7345*5113495bSYour Name 	}
7346*5113495bSYour Name 
7347*5113495bSYour Name 	ret = wmi_unified_register_event_handler(wmi_handle, event_id,
7348*5113495bSYour Name 						 handler_func, rx_ctx);
7349*5113495bSYour Name 
7350*5113495bSYour Name 	return qdf_status_to_os_return(ret);
7351*5113495bSYour Name }
7352*5113495bSYour Name 
7353*5113495bSYour Name /**
7354*5113495bSYour Name  * target_if_spectral_wmi_unified_unregister_event_handler() - Wrapper function
7355*5113495bSYour Name  * to unregister WMI event handler
7356*5113495bSYour Name  * @psoc: Pointer to psoc object
7357*5113495bSYour Name  * @event_id: Event id
7358*5113495bSYour Name  *
7359*5113495bSYour Name  * Wrapper function to unregister WMI event handler
7360*5113495bSYour Name  *
7361*5113495bSYour Name  * Return: 0 for success else failure
7362*5113495bSYour Name  */
7363*5113495bSYour Name static int
target_if_spectral_wmi_unified_unregister_event_handler(struct wlan_objmgr_psoc * psoc,wmi_conv_event_id event_id)7364*5113495bSYour Name target_if_spectral_wmi_unified_unregister_event_handler(
7365*5113495bSYour Name 				struct wlan_objmgr_psoc *psoc,
7366*5113495bSYour Name 				wmi_conv_event_id event_id)
7367*5113495bSYour Name {
7368*5113495bSYour Name 	wmi_unified_t wmi_handle;
7369*5113495bSYour Name 	QDF_STATUS ret;
7370*5113495bSYour Name 
7371*5113495bSYour Name 	if (!psoc) {
7372*5113495bSYour Name 		spectral_err("psoc is null");
7373*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
7374*5113495bSYour Name 	}
7375*5113495bSYour Name 
7376*5113495bSYour Name 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7377*5113495bSYour Name 	if (!wmi_handle) {
7378*5113495bSYour Name 		spectral_err("WMI handle is null");
7379*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
7380*5113495bSYour Name 	}
7381*5113495bSYour Name 
7382*5113495bSYour Name 	ret = wmi_unified_unregister_event_handler(wmi_handle, event_id);
7383*5113495bSYour Name 
7384*5113495bSYour Name 	return qdf_status_to_os_return(ret);
7385*5113495bSYour Name }
7386*5113495bSYour Name 
7387*5113495bSYour Name /**
7388*5113495bSYour Name  * target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param() - Wrapper
7389*5113495bSYour Name  * function to extract fixed parameters from start scan response event
7390*5113495bSYour Name  * @psoc: Pointer to psoc object
7391*5113495bSYour Name  * @evt_buf: Event buffer
7392*5113495bSYour Name  * @param: Start scan response parameters
7393*5113495bSYour Name  *
7394*5113495bSYour Name  * Wrapper function to extract fixed parameters from start scan response event
7395*5113495bSYour Name  *
7396*5113495bSYour Name  * Return: QDF_STATUS
7397*5113495bSYour Name  */
7398*5113495bSYour Name static QDF_STATUS
target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param(struct wlan_objmgr_psoc * psoc,uint8_t * evt_buf,struct spectral_startscan_resp_params * param)7399*5113495bSYour Name target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param(
7400*5113495bSYour Name 			struct wlan_objmgr_psoc *psoc,
7401*5113495bSYour Name 			uint8_t *evt_buf,
7402*5113495bSYour Name 			struct spectral_startscan_resp_params *param)
7403*5113495bSYour Name {
7404*5113495bSYour Name 	wmi_unified_t wmi_handle;
7405*5113495bSYour Name 
7406*5113495bSYour Name 	if (!psoc) {
7407*5113495bSYour Name 		spectral_err("psoc is null");
7408*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
7409*5113495bSYour Name 	}
7410*5113495bSYour Name 
7411*5113495bSYour Name 	if (!evt_buf) {
7412*5113495bSYour Name 		spectral_err("WMI event buffer is null");
7413*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
7414*5113495bSYour Name 	}
7415*5113495bSYour Name 
7416*5113495bSYour Name 	if (!param) {
7417*5113495bSYour Name 		spectral_err("Spectral startscan response parameters is null");
7418*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
7419*5113495bSYour Name 	}
7420*5113495bSYour Name 
7421*5113495bSYour Name 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7422*5113495bSYour Name 	if (!wmi_handle) {
7423*5113495bSYour Name 		spectral_err("WMI handle is null");
7424*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
7425*5113495bSYour Name 	}
7426*5113495bSYour Name 
7427*5113495bSYour Name 	return wmi_extract_pdev_sscan_fw_cmd_fixed_param(wmi_handle, evt_buf,
7428*5113495bSYour Name 							 param);
7429*5113495bSYour Name }
7430*5113495bSYour Name 
7431*5113495bSYour Name /**
7432*5113495bSYour Name  * target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index() - Wrapper
7433*5113495bSYour Name  * function to extract start and end indices of primary 80 MHz, 5 MHz and
7434*5113495bSYour Name  * secondary 80 MHz FFT bins
7435*5113495bSYour Name  * @psoc: Pointer to psoc object
7436*5113495bSYour Name  * @evt_buf: Event buffer
7437*5113495bSYour Name  * @param: FFT bin start and end indices
7438*5113495bSYour Name  *
7439*5113495bSYour Name  * Wrapper function to extract start and end indices of primary 80 MHz, 5 MHz
7440*5113495bSYour Name  * and secondary 80 MHz FFT bins
7441*5113495bSYour Name  *
7442*5113495bSYour Name  * Return: QDF_STATUS
7443*5113495bSYour Name  */
7444*5113495bSYour Name static QDF_STATUS
target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index(struct wlan_objmgr_psoc * psoc,uint8_t * evt_buf,struct spectral_fft_bin_markers_160_165mhz * param)7445*5113495bSYour Name target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index(
7446*5113495bSYour Name 			struct wlan_objmgr_psoc *psoc,
7447*5113495bSYour Name 			uint8_t *evt_buf,
7448*5113495bSYour Name 			struct spectral_fft_bin_markers_160_165mhz *param)
7449*5113495bSYour Name {
7450*5113495bSYour Name 	wmi_unified_t wmi_handle;
7451*5113495bSYour Name 
7452*5113495bSYour Name 	if (!psoc) {
7453*5113495bSYour Name 		spectral_err("psoc is null");
7454*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
7455*5113495bSYour Name 	}
7456*5113495bSYour Name 
7457*5113495bSYour Name 	if (!evt_buf) {
7458*5113495bSYour Name 		spectral_err("WMI event buffer is null");
7459*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
7460*5113495bSYour Name 	}
7461*5113495bSYour Name 
7462*5113495bSYour Name 	if (!param) {
7463*5113495bSYour Name 		spectral_err("Spectral FFT bin markers is null");
7464*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
7465*5113495bSYour Name 	}
7466*5113495bSYour Name 
7467*5113495bSYour Name 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7468*5113495bSYour Name 	if (!wmi_handle) {
7469*5113495bSYour Name 		spectral_err("WMI handle is null");
7470*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
7471*5113495bSYour Name 	}
7472*5113495bSYour Name 
7473*5113495bSYour Name 	return wmi_extract_pdev_sscan_fft_bin_index(wmi_handle, evt_buf, param);
7474*5113495bSYour Name }
7475*5113495bSYour Name 
7476*5113495bSYour Name /**
7477*5113495bSYour Name  * target_if_spectral_get_psoc_from_scn_handle() - Wrapper function to get psoc
7478*5113495bSYour Name  * object from scn handle
7479*5113495bSYour Name  * @scn: scn handle
7480*5113495bSYour Name  *
7481*5113495bSYour Name  * Wrapper function to get psoc object from scn handle
7482*5113495bSYour Name  *
7483*5113495bSYour Name  * Return: Pointer to psoc object
7484*5113495bSYour Name  */
7485*5113495bSYour Name static struct wlan_objmgr_psoc *
target_if_spectral_get_psoc_from_scn_handle(ol_scn_t scn)7486*5113495bSYour Name target_if_spectral_get_psoc_from_scn_handle(ol_scn_t scn)
7487*5113495bSYour Name {
7488*5113495bSYour Name 	if (!scn) {
7489*5113495bSYour Name 		spectral_err("scn is null");
7490*5113495bSYour Name 		return NULL;
7491*5113495bSYour Name 	}
7492*5113495bSYour Name 
7493*5113495bSYour Name 	return target_if_get_psoc_from_scn_hdl(scn);
7494*5113495bSYour Name }
7495*5113495bSYour Name 
7496*5113495bSYour Name /**
7497*5113495bSYour Name  * target_if_extract_pdev_spectral_session_chan_info() - Wrapper
7498*5113495bSYour Name  * function to extract channel information for a spectral scan session
7499*5113495bSYour Name  * @psoc: Pointer to psoc object
7500*5113495bSYour Name  * @evt_buf: Event buffer
7501*5113495bSYour Name  * @chan_info: Spectral session channel information data structure to be filled
7502*5113495bSYour Name  * by this API
7503*5113495bSYour Name  *
7504*5113495bSYour Name  * Return: QDF_STATUS of operation
7505*5113495bSYour Name  */
7506*5113495bSYour Name static QDF_STATUS
target_if_extract_pdev_spectral_session_chan_info(struct wlan_objmgr_psoc * psoc,void * evt_buf,struct spectral_session_chan_info * chan_info)7507*5113495bSYour Name target_if_extract_pdev_spectral_session_chan_info(
7508*5113495bSYour Name 			struct wlan_objmgr_psoc *psoc,
7509*5113495bSYour Name 			void *evt_buf,
7510*5113495bSYour Name 			struct spectral_session_chan_info *chan_info)
7511*5113495bSYour Name {
7512*5113495bSYour Name 	wmi_unified_t wmi_handle;
7513*5113495bSYour Name 
7514*5113495bSYour Name 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7515*5113495bSYour Name 	if (!wmi_handle) {
7516*5113495bSYour Name 		spectral_err("WMI handle is null");
7517*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
7518*5113495bSYour Name 	}
7519*5113495bSYour Name 
7520*5113495bSYour Name 	return wmi_extract_pdev_spectral_session_chan_info(
7521*5113495bSYour Name 			wmi_handle, evt_buf, chan_info);
7522*5113495bSYour Name }
7523*5113495bSYour Name 
7524*5113495bSYour Name /**
7525*5113495bSYour Name  * target_if_extract_pdev_spectral_session_detector_info() - Wrapper
7526*5113495bSYour Name  * function to extract detector information for a spectral scan session
7527*5113495bSYour Name  * @psoc: Pointer to psoc object
7528*5113495bSYour Name  * @evt_buf: Event buffer
7529*5113495bSYour Name  * @det_info: Spectral session detector information data structure to be filled
7530*5113495bSYour Name  * by this API
7531*5113495bSYour Name  * @det_info_idx: index in the array of spectral scan detector info TLVs
7532*5113495bSYour Name  *
7533*5113495bSYour Name  * Return: QDF_STATUS of operation
7534*5113495bSYour Name  */
7535*5113495bSYour Name static QDF_STATUS
target_if_extract_pdev_spectral_session_detector_info(struct wlan_objmgr_psoc * psoc,void * evt_buf,struct spectral_session_det_info * det_info,uint8_t det_info_idx)7536*5113495bSYour Name target_if_extract_pdev_spectral_session_detector_info(
7537*5113495bSYour Name 			struct wlan_objmgr_psoc *psoc, void *evt_buf,
7538*5113495bSYour Name 			struct spectral_session_det_info *det_info,
7539*5113495bSYour Name 			uint8_t det_info_idx)
7540*5113495bSYour Name {
7541*5113495bSYour Name 	wmi_unified_t wmi_handle;
7542*5113495bSYour Name 
7543*5113495bSYour Name 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7544*5113495bSYour Name 	if (!wmi_handle) {
7545*5113495bSYour Name 		spectral_err("WMI handle is null");
7546*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
7547*5113495bSYour Name 	}
7548*5113495bSYour Name 
7549*5113495bSYour Name 	return wmi_extract_pdev_spectral_session_detector_info(
7550*5113495bSYour Name 				wmi_handle, evt_buf, det_info, det_info_idx);
7551*5113495bSYour Name }
7552*5113495bSYour Name 
7553*5113495bSYour Name QDF_STATUS
target_if_wmi_extract_spectral_caps_fixed_param(struct wlan_objmgr_psoc * psoc,uint8_t * evt_buf,struct spectral_capabilities_event_params * param)7554*5113495bSYour Name target_if_wmi_extract_spectral_caps_fixed_param(
7555*5113495bSYour Name 			struct wlan_objmgr_psoc *psoc,
7556*5113495bSYour Name 			uint8_t *evt_buf,
7557*5113495bSYour Name 			struct spectral_capabilities_event_params *param)
7558*5113495bSYour Name {
7559*5113495bSYour Name 	wmi_unified_t wmi_handle;
7560*5113495bSYour Name 
7561*5113495bSYour Name 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7562*5113495bSYour Name 	if (!wmi_handle) {
7563*5113495bSYour Name 		spectral_err("WMI handle is null");
7564*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
7565*5113495bSYour Name 	}
7566*5113495bSYour Name 
7567*5113495bSYour Name 	return wmi_extract_spectral_caps_fixed_param(wmi_handle, evt_buf,
7568*5113495bSYour Name 						     param);
7569*5113495bSYour Name }
7570*5113495bSYour Name 
7571*5113495bSYour Name QDF_STATUS
target_if_wmi_extract_spectral_scan_bw_caps(struct wlan_objmgr_psoc * psoc,uint8_t * evt_buf,struct spectral_scan_bw_capabilities * bw_caps)7572*5113495bSYour Name target_if_wmi_extract_spectral_scan_bw_caps(
7573*5113495bSYour Name 			struct wlan_objmgr_psoc *psoc,
7574*5113495bSYour Name 			uint8_t *evt_buf,
7575*5113495bSYour Name 			struct spectral_scan_bw_capabilities *bw_caps)
7576*5113495bSYour Name {
7577*5113495bSYour Name 	wmi_unified_t wmi_handle;
7578*5113495bSYour Name 
7579*5113495bSYour Name 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7580*5113495bSYour Name 	if (!wmi_handle) {
7581*5113495bSYour Name 		spectral_err("WMI handle is null");
7582*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
7583*5113495bSYour Name 	}
7584*5113495bSYour Name 
7585*5113495bSYour Name 	return wmi_extract_spectral_scan_bw_caps(wmi_handle, evt_buf, bw_caps);
7586*5113495bSYour Name }
7587*5113495bSYour Name 
7588*5113495bSYour Name QDF_STATUS
target_if_wmi_extract_spectral_fft_size_caps(struct wlan_objmgr_psoc * psoc,uint8_t * evt_buf,struct spectral_fft_size_capabilities * fft_size_caps)7589*5113495bSYour Name target_if_wmi_extract_spectral_fft_size_caps(
7590*5113495bSYour Name 			struct wlan_objmgr_psoc *psoc,
7591*5113495bSYour Name 			uint8_t *evt_buf,
7592*5113495bSYour Name 			struct spectral_fft_size_capabilities *fft_size_caps)
7593*5113495bSYour Name {
7594*5113495bSYour Name 	wmi_unified_t wmi_handle;
7595*5113495bSYour Name 
7596*5113495bSYour Name 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7597*5113495bSYour Name 	if (!wmi_handle) {
7598*5113495bSYour Name 		spectral_err("WMI handle is null");
7599*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
7600*5113495bSYour Name 	}
7601*5113495bSYour Name 
7602*5113495bSYour Name 	return wmi_extract_spectral_fft_size_caps(wmi_handle, evt_buf,
7603*5113495bSYour Name 						  fft_size_caps);
7604*5113495bSYour Name }
7605*5113495bSYour Name #endif
7606*5113495bSYour Name 
7607*5113495bSYour Name /**
7608*5113495bSYour Name  * target_if_update_det_info_in_spectral_session() - Update detector
7609*5113495bSYour Name  * information in spectral scan session
7610*5113495bSYour Name  * @spectral: Spectral LMAC object
7611*5113495bSYour Name  * @det_info: Pointer to spectral session detector information
7612*5113495bSYour Name  * @smode: Spectral scan mode
7613*5113495bSYour Name  *
7614*5113495bSYour Name  * Return: QDF_STATUS of operation
7615*5113495bSYour Name  */
7616*5113495bSYour Name static QDF_STATUS
target_if_update_det_info_in_spectral_session(struct target_if_spectral * spectral,const struct spectral_session_det_info * det_info,enum spectral_scan_mode smode)7617*5113495bSYour Name target_if_update_det_info_in_spectral_session(
7618*5113495bSYour Name 	struct target_if_spectral *spectral,
7619*5113495bSYour Name 	const struct spectral_session_det_info *det_info,
7620*5113495bSYour Name 	enum spectral_scan_mode smode)
7621*5113495bSYour Name {
7622*5113495bSYour Name 	struct per_session_det_map *det_map;
7623*5113495bSYour Name 	struct per_session_dest_det_info *dest_det_info;
7624*5113495bSYour Name 
7625*5113495bSYour Name 	if (!spectral) {
7626*5113495bSYour Name 		spectral_err_rl("Spectral LMAC object is null");
7627*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
7628*5113495bSYour Name 	}
7629*5113495bSYour Name 
7630*5113495bSYour Name 	if (det_info->det_id >= MAX_DETECTORS_PER_PDEV) {
7631*5113495bSYour Name 		spectral_err_rl("Detector Id: %u exceeding Max detectors.",
7632*5113495bSYour Name 				det_info->det_id);
7633*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
7634*5113495bSYour Name 	}
7635*5113495bSYour Name 
7636*5113495bSYour Name 	qdf_spin_lock_bh(&spectral->session_det_map_lock);
7637*5113495bSYour Name 
7638*5113495bSYour Name 	det_map = &spectral->det_map[det_info->det_id];
7639*5113495bSYour Name 	dest_det_info = &det_map->dest_det_info[0];
7640*5113495bSYour Name 
7641*5113495bSYour Name 	dest_det_info->start_freq = det_info->start_freq;
7642*5113495bSYour Name 	dest_det_info->end_freq = det_info->end_freq;
7643*5113495bSYour Name 
7644*5113495bSYour Name 	qdf_spin_unlock_bh(&spectral->session_det_map_lock);
7645*5113495bSYour Name 
7646*5113495bSYour Name 	/* This detector will be used for this smode throughout this session */
7647*5113495bSYour Name 	spectral->rparams.detid_mode_table[det_info->det_id] = smode;
7648*5113495bSYour Name 
7649*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
7650*5113495bSYour Name }
7651*5113495bSYour Name 
7652*5113495bSYour Name /**
7653*5113495bSYour Name  * target_if_update_chan_info_in_spectral_session() - Update channel information
7654*5113495bSYour Name  * in spectral scan session
7655*5113495bSYour Name  * @spectral: Spectral LMAC object
7656*5113495bSYour Name  * @chan_info: Pointer to spectral session channel information
7657*5113495bSYour Name  * @smode: Spectral scan mode
7658*5113495bSYour Name  *
7659*5113495bSYour Name  * Return: QDF_STATUS of operation
7660*5113495bSYour Name  */
7661*5113495bSYour Name static QDF_STATUS
target_if_update_chan_info_in_spectral_session(struct target_if_spectral * spectral,const struct spectral_session_chan_info * chan_info,enum spectral_scan_mode smode)7662*5113495bSYour Name target_if_update_chan_info_in_spectral_session(
7663*5113495bSYour Name 	struct target_if_spectral *spectral,
7664*5113495bSYour Name 	const struct spectral_session_chan_info *chan_info,
7665*5113495bSYour Name 	enum spectral_scan_mode smode)
7666*5113495bSYour Name {
7667*5113495bSYour Name 	struct per_session_report_info *rpt_info;
7668*5113495bSYour Name 
7669*5113495bSYour Name 	if (!spectral) {
7670*5113495bSYour Name 		spectral_err_rl("Spectral LMAC object is null");
7671*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
7672*5113495bSYour Name 	}
7673*5113495bSYour Name 
7674*5113495bSYour Name 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
7675*5113495bSYour Name 		spectral_err_rl("Invalid Spectral scan mode :%u", smode);
7676*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
7677*5113495bSYour Name 	}
7678*5113495bSYour Name 
7679*5113495bSYour Name 	qdf_spin_lock_bh(&spectral->session_report_info_lock);
7680*5113495bSYour Name 	rpt_info = &spectral->report_info[smode];
7681*5113495bSYour Name 
7682*5113495bSYour Name 	/* Update per-session report info */
7683*5113495bSYour Name 	rpt_info->pri20_freq = chan_info->operating_pri20_freq;
7684*5113495bSYour Name 	rpt_info->cfreq1 = chan_info->operating_cfreq1;
7685*5113495bSYour Name 	rpt_info->cfreq2 = chan_info->operating_cfreq2;
7686*5113495bSYour Name 	rpt_info->operating_bw = chan_info->operating_bw;
7687*5113495bSYour Name 	rpt_info->sscan_cfreq1 = chan_info->sscan_cfreq1;
7688*5113495bSYour Name 	rpt_info->sscan_cfreq2 = chan_info->sscan_cfreq2;
7689*5113495bSYour Name 	rpt_info->sscan_bw = chan_info->sscan_bw;
7690*5113495bSYour Name 
7691*5113495bSYour Name 	/* num_spans depends on sscan_bw, update it */
7692*5113495bSYour Name 	rpt_info->num_spans = target_if_spectral_get_num_spans(
7693*5113495bSYour Name 					spectral->pdev_obj,
7694*5113495bSYour Name 					rpt_info->sscan_bw);
7695*5113495bSYour Name 	if (rpt_info->num_spans == INVALID_SPAN_NUM) {
7696*5113495bSYour Name 		spectral_err_rl("Invalid number of spans: %u",
7697*5113495bSYour Name 				rpt_info->num_spans);
7698*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
7699*5113495bSYour Name 	}
7700*5113495bSYour Name 
7701*5113495bSYour Name 	rpt_info->valid = true;
7702*5113495bSYour Name 
7703*5113495bSYour Name 	qdf_spin_unlock_bh(&spectral->session_report_info_lock);
7704*5113495bSYour Name 
7705*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
7706*5113495bSYour Name }
7707*5113495bSYour Name 
7708*5113495bSYour Name /**
7709*5113495bSYour Name  * target_if_spectral_fw_param_event_handler() - WMI event handler to
7710*5113495bSYour Name  * process start scan response event
7711*5113495bSYour Name  * @scn: Pointer to scn object
7712*5113495bSYour Name  * @data_buf: Pointer to event buffer
7713*5113495bSYour Name  * @data_len: Length of event buffer
7714*5113495bSYour Name  *
7715*5113495bSYour Name  * Return: 0 for success, else failure
7716*5113495bSYour Name  */
7717*5113495bSYour Name static int
target_if_spectral_fw_param_event_handler(ol_scn_t scn,uint8_t * data_buf,uint32_t data_len)7718*5113495bSYour Name target_if_spectral_fw_param_event_handler(ol_scn_t scn, uint8_t *data_buf,
7719*5113495bSYour Name 					  uint32_t data_len)
7720*5113495bSYour Name {
7721*5113495bSYour Name 	QDF_STATUS status;
7722*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
7723*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev;
7724*5113495bSYour Name 	struct wmi_unified *wmi_handle;
7725*5113495bSYour Name 	struct spectral_startscan_resp_params event_params = {0};
7726*5113495bSYour Name 	struct target_if_psoc_spectral *psoc_spectral;
7727*5113495bSYour Name 	struct target_if_spectral *spectral;
7728*5113495bSYour Name 	bool is_session_info_expected;
7729*5113495bSYour Name 
7730*5113495bSYour Name 	if (!scn) {
7731*5113495bSYour Name 		spectral_err("scn handle is null");
7732*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
7733*5113495bSYour Name 	}
7734*5113495bSYour Name 
7735*5113495bSYour Name 	if (!data_buf) {
7736*5113495bSYour Name 		spectral_err("WMI event buffer null");
7737*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
7738*5113495bSYour Name 	}
7739*5113495bSYour Name 
7740*5113495bSYour Name 	psoc = target_if_spectral_get_psoc_from_scn_handle(scn);
7741*5113495bSYour Name 	if (!psoc) {
7742*5113495bSYour Name 		spectral_err("psoc is null");
7743*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
7744*5113495bSYour Name 	}
7745*5113495bSYour Name 
7746*5113495bSYour Name 	psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
7747*5113495bSYour Name 	if (!psoc_spectral) {
7748*5113495bSYour Name 		spectral_err("spectral object is null");
7749*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
7750*5113495bSYour Name 	}
7751*5113495bSYour Name 
7752*5113495bSYour Name 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7753*5113495bSYour Name 	if (!wmi_handle) {
7754*5113495bSYour Name 		spectral_err("WMI handle is null");
7755*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
7756*5113495bSYour Name 	}
7757*5113495bSYour Name 
7758*5113495bSYour Name 	status = target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param(
7759*5113495bSYour Name 				psoc, data_buf, &event_params);
7760*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
7761*5113495bSYour Name 		spectral_err("unable to extract sscan fw fixed params");
7762*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
7763*5113495bSYour Name 	}
7764*5113495bSYour Name 
7765*5113495bSYour Name 	if (event_params.smode >= SPECTRAL_SCAN_MODE_MAX ||
7766*5113495bSYour Name 	    event_params.smode < SPECTRAL_SCAN_MODE_NORMAL) {
7767*5113495bSYour Name 		spectral_err("Invalid smode %d", event_params.smode);
7768*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
7769*5113495bSYour Name 	}
7770*5113495bSYour Name 
7771*5113495bSYour Name 	pdev = wlan_objmgr_get_pdev_by_id(psoc, event_params.pdev_id,
7772*5113495bSYour Name 					  WLAN_SPECTRAL_ID);
7773*5113495bSYour Name 	if (!pdev) {
7774*5113495bSYour Name 		spectral_err("pdev is null");
7775*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
7776*5113495bSYour Name 	}
7777*5113495bSYour Name 
7778*5113495bSYour Name 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
7779*5113495bSYour Name 	if (!spectral) {
7780*5113495bSYour Name 		spectral_err("spectral object is null");
7781*5113495bSYour Name 		status = QDF_STATUS_E_FAILURE;
7782*5113495bSYour Name 		goto release_pdev_ref;
7783*5113495bSYour Name 	}
7784*5113495bSYour Name 
7785*5113495bSYour Name 	if (event_params.num_fft_bin_index == 1) {
7786*5113495bSYour Name 		status =
7787*5113495bSYour Name 			target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index(
7788*5113495bSYour Name 				psoc, data_buf,
7789*5113495bSYour Name 				&spectral->rparams.marker[event_params.smode]);
7790*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
7791*5113495bSYour Name 			spectral_err("unable to extract sscan fw fixed params");
7792*5113495bSYour Name 			goto release_pdev_ref;
7793*5113495bSYour Name 		}
7794*5113495bSYour Name 	} else {
7795*5113495bSYour Name 		spectral->rparams.marker[event_params.smode].is_valid = false;
7796*5113495bSYour Name 	}
7797*5113495bSYour Name 
7798*5113495bSYour Name 	status = spectral_is_session_info_expected_from_target(
7799*5113495bSYour Name 					pdev, &is_session_info_expected);
7800*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
7801*5113495bSYour Name 		spectral_err("Failed to check if session info is expected");
7802*5113495bSYour Name 		goto release_pdev_ref;
7803*5113495bSYour Name 	}
7804*5113495bSYour Name 
7805*5113495bSYour Name 	if (is_session_info_expected) {
7806*5113495bSYour Name 		struct spectral_session_chan_info chan_info;
7807*5113495bSYour Name 		uint8_t det_info_idx = 0;
7808*5113495bSYour Name 
7809*5113495bSYour Name 		status = target_if_extract_pdev_spectral_session_chan_info(
7810*5113495bSYour Name 				psoc, data_buf, &chan_info);
7811*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
7812*5113495bSYour Name 			spectral_err("Unable to extract spectral session channel info");
7813*5113495bSYour Name 			goto release_pdev_ref;
7814*5113495bSYour Name 		}
7815*5113495bSYour Name 
7816*5113495bSYour Name 		status = target_if_update_chan_info_in_spectral_session(
7817*5113495bSYour Name 				spectral, &chan_info, event_params.smode);
7818*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
7819*5113495bSYour Name 			spectral_err("Unable to update channel info");
7820*5113495bSYour Name 			goto release_pdev_ref;
7821*5113495bSYour Name 		}
7822*5113495bSYour Name 
7823*5113495bSYour Name 		/* FFT bins info depends upon sscan_bw, update it */
7824*5113495bSYour Name 		status = target_if_populate_fft_bins_info(spectral,
7825*5113495bSYour Name 							  event_params.smode);
7826*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
7827*5113495bSYour Name 			spectral_err("Failed to populate FFT bins info");
7828*5113495bSYour Name 			goto release_pdev_ref;
7829*5113495bSYour Name 		}
7830*5113495bSYour Name 
7831*5113495bSYour Name 		/**
7832*5113495bSYour Name 		 * per-session det info that depends on sscan_bw needs to be
7833*5113495bSYour Name 		 * updated here
7834*5113495bSYour Name 		 */
7835*5113495bSYour Name 		status = target_if_spectral_populate_session_det_host_info(
7836*5113495bSYour Name 					spectral, event_params.smode);
7837*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
7838*5113495bSYour Name 			spectral_err("Failed to populate per-session det info");
7839*5113495bSYour Name 			goto release_pdev_ref;
7840*5113495bSYour Name 		}
7841*5113495bSYour Name 
7842*5113495bSYour Name 		for (; det_info_idx < event_params.num_det_info;
7843*5113495bSYour Name 		     ++det_info_idx) {
7844*5113495bSYour Name 			struct spectral_session_det_info det_info;
7845*5113495bSYour Name 
7846*5113495bSYour Name 			status =
7847*5113495bSYour Name 			  target_if_extract_pdev_spectral_session_detector_info
7848*5113495bSYour Name 				(psoc, data_buf, &det_info, det_info_idx);
7849*5113495bSYour Name 
7850*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(status)) {
7851*5113495bSYour Name 				spectral_err("Unable to extract spectral session detector info for %u",
7852*5113495bSYour Name 					     det_info_idx);
7853*5113495bSYour Name 				goto release_pdev_ref;
7854*5113495bSYour Name 			}
7855*5113495bSYour Name 
7856*5113495bSYour Name 			status = target_if_update_det_info_in_spectral_session(
7857*5113495bSYour Name 					spectral, &det_info,
7858*5113495bSYour Name 					event_params.smode);
7859*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(status)) {
7860*5113495bSYour Name 				spectral_err("Unable to update detector info");
7861*5113495bSYour Name 				goto release_pdev_ref;
7862*5113495bSYour Name 			}
7863*5113495bSYour Name 		}
7864*5113495bSYour Name 	}
7865*5113495bSYour Name 
7866*5113495bSYour Name 	status = QDF_STATUS_SUCCESS;
7867*5113495bSYour Name 
7868*5113495bSYour Name release_pdev_ref:
7869*5113495bSYour Name 	wlan_objmgr_pdev_release_ref(pdev, WLAN_SPECTRAL_ID);
7870*5113495bSYour Name 	return qdf_status_to_os_return(status);
7871*5113495bSYour Name }
7872*5113495bSYour Name 
7873*5113495bSYour Name /**
7874*5113495bSYour Name  * target_if_spectral_capabilities_event_handler() - Handler for the Spectral
7875*5113495bSYour Name  * Capabilities event
7876*5113495bSYour Name  * @scn: Pointer to scn object
7877*5113495bSYour Name  * @data_buf: Pointer to event buffer
7878*5113495bSYour Name  * @data_len: Length of event buffer
7879*5113495bSYour Name  *
7880*5113495bSYour Name  * Return: 0 for success, else failure
7881*5113495bSYour Name  */
7882*5113495bSYour Name static int
target_if_spectral_capabilities_event_handler(ol_scn_t scn,uint8_t * data_buf,uint32_t data_len)7883*5113495bSYour Name target_if_spectral_capabilities_event_handler(ol_scn_t scn, uint8_t *data_buf,
7884*5113495bSYour Name 					      uint32_t data_len)
7885*5113495bSYour Name {
7886*5113495bSYour Name 	QDF_STATUS status;
7887*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
7888*5113495bSYour Name 	struct wmi_unified *wmi_handle;
7889*5113495bSYour Name 	struct spectral_capabilities_event_params event_params = {0};
7890*5113495bSYour Name 	struct spectral_scan_bw_capabilities *bw_caps;
7891*5113495bSYour Name 	struct spectral_fft_size_capabilities *fft_size_caps;
7892*5113495bSYour Name 
7893*5113495bSYour Name 	if (!scn) {
7894*5113495bSYour Name 		spectral_err("scn handle is null");
7895*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
7896*5113495bSYour Name 	}
7897*5113495bSYour Name 
7898*5113495bSYour Name 	if (!data_buf) {
7899*5113495bSYour Name 		spectral_err("WMI event buffer null");
7900*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
7901*5113495bSYour Name 	}
7902*5113495bSYour Name 
7903*5113495bSYour Name 	psoc = target_if_spectral_get_psoc_from_scn_handle(scn);
7904*5113495bSYour Name 	if (!psoc) {
7905*5113495bSYour Name 		spectral_err("psoc is null");
7906*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
7907*5113495bSYour Name 	}
7908*5113495bSYour Name 
7909*5113495bSYour Name 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7910*5113495bSYour Name 	if (!wmi_handle) {
7911*5113495bSYour Name 		spectral_err("WMI handle is null");
7912*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
7913*5113495bSYour Name 	}
7914*5113495bSYour Name 
7915*5113495bSYour Name 	status = target_if_wmi_extract_spectral_caps_fixed_param(
7916*5113495bSYour Name 				psoc, data_buf, &event_params);
7917*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
7918*5113495bSYour Name 		spectral_err("Failed to extract fixed parameters");
7919*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
7920*5113495bSYour Name 	}
7921*5113495bSYour Name 
7922*5113495bSYour Name 	/* There should be atleast one capability */
7923*5113495bSYour Name 	if (!event_params.num_sscan_bw_caps) {
7924*5113495bSYour Name 		spectral_err("Number of spectral_scan_bw_capabilities is less than one.");
7925*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
7926*5113495bSYour Name 	}
7927*5113495bSYour Name 
7928*5113495bSYour Name 	if (!event_params.num_fft_size_caps) {
7929*5113495bSYour Name 		spectral_err("Number of spectral_scan_fft_size_capabilities is less than one.");
7930*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
7931*5113495bSYour Name 	}
7932*5113495bSYour Name 
7933*5113495bSYour Name 	bw_caps = qdf_mem_malloc(
7934*5113495bSYour Name 			sizeof(*bw_caps) * event_params.num_sscan_bw_caps);
7935*5113495bSYour Name 	if (!bw_caps) {
7936*5113495bSYour Name 		spectral_err("memory allocation failed");
7937*5113495bSYour Name 		return qdf_status_to_os_return(QDF_STATUS_E_NOMEM);
7938*5113495bSYour Name 	}
7939*5113495bSYour Name 
7940*5113495bSYour Name 	status = target_if_wmi_extract_spectral_scan_bw_caps(psoc, data_buf,
7941*5113495bSYour Name 							     bw_caps);
7942*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
7943*5113495bSYour Name 		spectral_err("Failed to extract BW caps");
7944*5113495bSYour Name 		status = QDF_STATUS_E_FAILURE;
7945*5113495bSYour Name 		goto free_bw_caps;
7946*5113495bSYour Name 	}
7947*5113495bSYour Name 
7948*5113495bSYour Name 	fft_size_caps = qdf_mem_malloc(
7949*5113495bSYour Name 		sizeof(*fft_size_caps) * event_params.num_fft_size_caps);
7950*5113495bSYour Name 	if (!fft_size_caps) {
7951*5113495bSYour Name 		spectral_err("memory allocation failed");
7952*5113495bSYour Name 		status = QDF_STATUS_E_NOMEM;
7953*5113495bSYour Name 		goto free_bw_caps;
7954*5113495bSYour Name 	}
7955*5113495bSYour Name 
7956*5113495bSYour Name 	status = target_if_wmi_extract_spectral_fft_size_caps(psoc, data_buf,
7957*5113495bSYour Name 							      fft_size_caps);
7958*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
7959*5113495bSYour Name 		spectral_err("Failed to extract fft size caps");
7960*5113495bSYour Name 		status = QDF_STATUS_E_FAILURE;
7961*5113495bSYour Name 		goto free_fft_size_caps;
7962*5113495bSYour Name 	}
7963*5113495bSYour Name 
7964*5113495bSYour Name 	status = QDF_STATUS_SUCCESS;
7965*5113495bSYour Name 
7966*5113495bSYour Name free_fft_size_caps:
7967*5113495bSYour Name 	qdf_mem_free(fft_size_caps);
7968*5113495bSYour Name 
7969*5113495bSYour Name free_bw_caps:
7970*5113495bSYour Name 	qdf_mem_free(bw_caps);
7971*5113495bSYour Name 
7972*5113495bSYour Name 	return qdf_status_to_os_return(status);
7973*5113495bSYour Name }
7974*5113495bSYour Name 
7975*5113495bSYour Name static QDF_STATUS
target_if_spectral_register_events(struct wlan_objmgr_psoc * psoc)7976*5113495bSYour Name target_if_spectral_register_events(struct wlan_objmgr_psoc *psoc)
7977*5113495bSYour Name {
7978*5113495bSYour Name 	int ret;
7979*5113495bSYour Name 
7980*5113495bSYour Name 	if (!psoc) {
7981*5113495bSYour Name 		spectral_err("psoc is null");
7982*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
7983*5113495bSYour Name 	}
7984*5113495bSYour Name 
7985*5113495bSYour Name 	ret = target_if_spectral_wmi_unified_register_event_handler(
7986*5113495bSYour Name 			psoc,
7987*5113495bSYour Name 			wmi_pdev_sscan_fw_param_eventid,
7988*5113495bSYour Name 			target_if_spectral_fw_param_event_handler,
7989*5113495bSYour Name 			WMI_RX_UMAC_CTX);
7990*5113495bSYour Name 
7991*5113495bSYour Name 	if (ret)
7992*5113495bSYour Name 		spectral_debug("event handler not supported, ret=%d", ret);
7993*5113495bSYour Name 
7994*5113495bSYour Name 	ret = target_if_spectral_wmi_unified_register_event_handler(
7995*5113495bSYour Name 			psoc,
7996*5113495bSYour Name 			wmi_spectral_capabilities_eventid,
7997*5113495bSYour Name 			target_if_spectral_capabilities_event_handler,
7998*5113495bSYour Name 			WMI_RX_UMAC_CTX);
7999*5113495bSYour Name 	if (ret)
8000*5113495bSYour Name 		spectral_debug("event handler not supported, ret=%d", ret);
8001*5113495bSYour Name 
8002*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
8003*5113495bSYour Name }
8004*5113495bSYour Name 
8005*5113495bSYour Name static QDF_STATUS
target_if_spectral_unregister_events(struct wlan_objmgr_psoc * psoc)8006*5113495bSYour Name target_if_spectral_unregister_events(struct wlan_objmgr_psoc *psoc)
8007*5113495bSYour Name {
8008*5113495bSYour Name 	int ret;
8009*5113495bSYour Name 
8010*5113495bSYour Name 	if (!psoc) {
8011*5113495bSYour Name 		spectral_err("psoc is null");
8012*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
8013*5113495bSYour Name 	}
8014*5113495bSYour Name 
8015*5113495bSYour Name 	target_if_spectral_wmi_unified_unregister_event_handler(
8016*5113495bSYour Name 			psoc, wmi_spectral_capabilities_eventid);
8017*5113495bSYour Name 
8018*5113495bSYour Name 	ret = target_if_spectral_wmi_unified_unregister_event_handler(
8019*5113495bSYour Name 			psoc, wmi_pdev_sscan_fw_param_eventid);
8020*5113495bSYour Name 
8021*5113495bSYour Name 	if (ret)
8022*5113495bSYour Name 		spectral_debug("Unregister WMI event handler failed, ret = %d",
8023*5113495bSYour Name 			       ret);
8024*5113495bSYour Name 
8025*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
8026*5113495bSYour Name }
8027*5113495bSYour Name 
8028*5113495bSYour Name void
target_if_sptrl_register_tx_ops(struct wlan_lmac_if_tx_ops * tx_ops)8029*5113495bSYour Name target_if_sptrl_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
8030*5113495bSYour Name {
8031*5113495bSYour Name 	tx_ops->sptrl_tx_ops.sptrlto_pdev_spectral_init =
8032*5113495bSYour Name 	    target_if_pdev_spectral_init;
8033*5113495bSYour Name 	tx_ops->sptrl_tx_ops.sptrlto_pdev_spectral_deinit =
8034*5113495bSYour Name 	    target_if_pdev_spectral_deinit;
8035*5113495bSYour Name 	tx_ops->sptrl_tx_ops.sptrlto_psoc_spectral_init =
8036*5113495bSYour Name 	    target_if_psoc_spectral_init;
8037*5113495bSYour Name 	tx_ops->sptrl_tx_ops.sptrlto_psoc_spectral_deinit =
8038*5113495bSYour Name 	    target_if_psoc_spectral_deinit;
8039*5113495bSYour Name 	tx_ops->sptrl_tx_ops.sptrlto_set_spectral_config =
8040*5113495bSYour Name 	    target_if_set_spectral_config;
8041*5113495bSYour Name 	tx_ops->sptrl_tx_ops.sptrlto_get_spectral_config =
8042*5113495bSYour Name 	    target_if_get_spectral_config;
8043*5113495bSYour Name 	tx_ops->sptrl_tx_ops.sptrlto_start_spectral_scan =
8044*5113495bSYour Name 	    target_if_start_spectral_scan;
8045*5113495bSYour Name 	tx_ops->sptrl_tx_ops.sptrlto_stop_spectral_scan =
8046*5113495bSYour Name 	    target_if_stop_spectral_scan;
8047*5113495bSYour Name 	tx_ops->sptrl_tx_ops.sptrlto_is_spectral_active =
8048*5113495bSYour Name 	    target_if_is_spectral_active;
8049*5113495bSYour Name 	tx_ops->sptrl_tx_ops.sptrlto_is_spectral_enabled =
8050*5113495bSYour Name 	    target_if_is_spectral_enabled;
8051*5113495bSYour Name 	tx_ops->sptrl_tx_ops.sptrlto_set_debug_level =
8052*5113495bSYour Name 	    target_if_set_debug_level;
8053*5113495bSYour Name 	tx_ops->sptrl_tx_ops.sptrlto_get_debug_level =
8054*5113495bSYour Name 	    target_if_get_debug_level;
8055*5113495bSYour Name 	tx_ops->sptrl_tx_ops.sptrlto_get_spectral_capinfo =
8056*5113495bSYour Name 	    target_if_get_spectral_capinfo;
8057*5113495bSYour Name 	tx_ops->sptrl_tx_ops.sptrlto_get_spectral_diagstats =
8058*5113495bSYour Name 	    target_if_get_spectral_diagstats;
8059*5113495bSYour Name 	tx_ops->sptrl_tx_ops.sptrlto_register_spectral_wmi_ops =
8060*5113495bSYour Name 	    target_if_register_spectral_wmi_ops;
8061*5113495bSYour Name 	tx_ops->sptrl_tx_ops.sptrlto_register_spectral_tgt_ops =
8062*5113495bSYour Name 	    target_if_register_spectral_tgt_ops;
8063*5113495bSYour Name 	tx_ops->sptrl_tx_ops.sptrlto_register_netlink_cb =
8064*5113495bSYour Name 	    target_if_register_netlink_cb;
8065*5113495bSYour Name 	tx_ops->sptrl_tx_ops.sptrlto_use_nl_bcast =
8066*5113495bSYour Name 	    target_if_use_nl_bcast;
8067*5113495bSYour Name 	tx_ops->sptrl_tx_ops.sptrlto_deregister_netlink_cb =
8068*5113495bSYour Name 	    target_if_deregister_netlink_cb;
8069*5113495bSYour Name 	tx_ops->sptrl_tx_ops.sptrlto_process_spectral_report =
8070*5113495bSYour Name 	    target_if_process_spectral_report;
8071*5113495bSYour Name 	tx_ops->sptrl_tx_ops.sptrlto_direct_dma_support =
8072*5113495bSYour Name 		target_if_spectral_direct_dma_support;
8073*5113495bSYour Name 	tx_ops->sptrl_tx_ops.sptrlto_register_events =
8074*5113495bSYour Name 		target_if_spectral_register_events;
8075*5113495bSYour Name 	tx_ops->sptrl_tx_ops.sptrlto_unregister_events =
8076*5113495bSYour Name 		target_if_spectral_unregister_events;
8077*5113495bSYour Name 	tx_ops->sptrl_tx_ops.sptrlto_init_pdev_feature_caps =
8078*5113495bSYour Name 		target_if_spectral_init_pdev_feature_caps;
8079*5113495bSYour Name 
8080*5113495bSYour Name 	target_if_sptrl_debug_register_tx_ops(tx_ops);
8081*5113495bSYour Name }
8082*5113495bSYour Name qdf_export_symbol(target_if_sptrl_register_tx_ops);
8083*5113495bSYour Name 
8084*5113495bSYour Name void
target_if_spectral_send_intf_found_msg(struct wlan_objmgr_pdev * pdev,uint16_t cw_int,uint32_t dcs_enabled)8085*5113495bSYour Name target_if_spectral_send_intf_found_msg(struct wlan_objmgr_pdev *pdev,
8086*5113495bSYour Name 				       uint16_t cw_int, uint32_t dcs_enabled)
8087*5113495bSYour Name {
8088*5113495bSYour Name 	struct spectral_samp_msg *msg = NULL;
8089*5113495bSYour Name 	struct target_if_spectral_ops *p_sops = NULL;
8090*5113495bSYour Name 	struct target_if_spectral *spectral = NULL;
8091*5113495bSYour Name 
8092*5113495bSYour Name 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
8093*5113495bSYour Name 
8094*5113495bSYour Name 	if (!spectral) {
8095*5113495bSYour Name 		spectral_err("SPECTRAL : Module doesn't exist");
8096*5113495bSYour Name 		return;
8097*5113495bSYour Name 	}
8098*5113495bSYour Name 
8099*5113495bSYour Name 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
8100*5113495bSYour Name 	if (!p_sops) {
8101*5113495bSYour Name 		spectral_err("p_sops is null");
8102*5113495bSYour Name 		return;
8103*5113495bSYour Name 	}
8104*5113495bSYour Name 
8105*5113495bSYour Name 	msg  = (struct spectral_samp_msg *)spectral->nl_cb.get_sbuff(
8106*5113495bSYour Name 			spectral->pdev_obj,
8107*5113495bSYour Name 			SPECTRAL_MSG_INTERFERENCE_NOTIFICATION,
8108*5113495bSYour Name 			SPECTRAL_MSG_BUF_NEW);
8109*5113495bSYour Name 
8110*5113495bSYour Name 	if (msg) {
8111*5113495bSYour Name 		msg->int_type = cw_int ?
8112*5113495bSYour Name 		    SPECTRAL_DCS_INT_CW : SPECTRAL_DCS_INT_WIFI;
8113*5113495bSYour Name 		msg->dcs_enabled = dcs_enabled;
8114*5113495bSYour Name 		msg->signature = SPECTRAL_SIGNATURE;
8115*5113495bSYour Name 		p_sops->get_mac_address(spectral, msg->macaddr);
8116*5113495bSYour Name 		if (spectral->send_phy_data
8117*5113495bSYour Name 				(pdev,
8118*5113495bSYour Name 				 SPECTRAL_MSG_INTERFERENCE_NOTIFICATION) == 0)
8119*5113495bSYour Name 			spectral->spectral_sent_msg++;
8120*5113495bSYour Name 	}
8121*5113495bSYour Name }
8122*5113495bSYour Name qdf_export_symbol(target_if_spectral_send_intf_found_msg);
8123*5113495bSYour Name 
8124*5113495bSYour Name QDF_STATUS
target_if_spectral_is_finite_scan(struct target_if_spectral * spectral,enum spectral_scan_mode smode,bool * finite_spectral_scan)8125*5113495bSYour Name target_if_spectral_is_finite_scan(struct target_if_spectral *spectral,
8126*5113495bSYour Name 				  enum spectral_scan_mode smode,
8127*5113495bSYour Name 				  bool *finite_spectral_scan)
8128*5113495bSYour Name {
8129*5113495bSYour Name 	struct target_if_finite_spectral_scan_params *finite_scan;
8130*5113495bSYour Name 
8131*5113495bSYour Name 	if (!spectral) {
8132*5113495bSYour Name 		spectral_err_rl("target if spectral object is null");
8133*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
8134*5113495bSYour Name 	}
8135*5113495bSYour Name 
8136*5113495bSYour Name 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
8137*5113495bSYour Name 		spectral_err_rl("invalid spectral mode %d", smode);
8138*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
8139*5113495bSYour Name 	}
8140*5113495bSYour Name 
8141*5113495bSYour Name 	if (!finite_spectral_scan) {
8142*5113495bSYour Name 		spectral_err_rl("Invalid pointer");
8143*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
8144*5113495bSYour Name 	}
8145*5113495bSYour Name 
8146*5113495bSYour Name 	finite_scan = &spectral->finite_scan[smode];
8147*5113495bSYour Name 	*finite_spectral_scan = finite_scan->finite_spectral_scan;
8148*5113495bSYour Name 
8149*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
8150*5113495bSYour Name }
8151*5113495bSYour Name 
8152*5113495bSYour Name QDF_STATUS
target_if_spectral_finite_scan_update(struct target_if_spectral * spectral,enum spectral_scan_mode smode)8153*5113495bSYour Name target_if_spectral_finite_scan_update(struct target_if_spectral *spectral,
8154*5113495bSYour Name 				      enum spectral_scan_mode smode)
8155*5113495bSYour Name {
8156*5113495bSYour Name 	struct target_if_finite_spectral_scan_params *finite_scan;
8157*5113495bSYour Name 
8158*5113495bSYour Name 	if (!spectral) {
8159*5113495bSYour Name 		spectral_err_rl("target if spectral object is null");
8160*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
8161*5113495bSYour Name 	}
8162*5113495bSYour Name 
8163*5113495bSYour Name 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
8164*5113495bSYour Name 		spectral_err_rl("Invalid Spectral mode");
8165*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
8166*5113495bSYour Name 	}
8167*5113495bSYour Name 
8168*5113495bSYour Name 	finite_scan = &spectral->finite_scan[smode];
8169*5113495bSYour Name 
8170*5113495bSYour Name 	if (!finite_scan->num_reports_expected) {
8171*5113495bSYour Name 		spectral_err_rl("Error, No reports expected");
8172*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
8173*5113495bSYour Name 	}
8174*5113495bSYour Name 
8175*5113495bSYour Name 	finite_scan->num_reports_expected--;
8176*5113495bSYour Name 	if (!finite_scan->num_reports_expected) {
8177*5113495bSYour Name 		QDF_STATUS status;
8178*5113495bSYour Name 		enum spectral_cp_error_code err;
8179*5113495bSYour Name 
8180*5113495bSYour Name 		/* received expected number of reports from target, stop scan */
8181*5113495bSYour Name 		status = target_if_stop_spectral_scan(spectral->pdev_obj, smode,
8182*5113495bSYour Name 						      &err);
8183*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
8184*5113495bSYour Name 			spectral_err_rl("Failed to stop finite Spectral scan");
8185*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
8186*5113495bSYour Name 		}
8187*5113495bSYour Name 		finite_scan->finite_spectral_scan =  false;
8188*5113495bSYour Name 	}
8189*5113495bSYour Name 
8190*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
8191*5113495bSYour Name }
8192