xref: /wlan-dirver/qca-wifi-host-cmn/target_if/spectral/target_if_spectral.c (revision 45a38684b07295822dc8eba39e293408f203eec8)
1 /*
2  * Copyright (c) 2011,2017-2020 The Linux Foundation. All rights reserved.
3  *
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <wlan_tgt_def_config.h>
21 #include <hif.h>
22 #include <target_type.h>
23 #include <hif_hw_version.h>
24 #include <wmi_unified_api.h>
25 #include <target_if_spectral.h>
26 #include <wlan_lmac_if_def.h>
27 #include <wlan_osif_priv.h>
28 #include <init_deinit_lmac.h>
29 #include <reg_services_public_struct.h>
30 #include <target_if_spectral_sim.h>
31 #include <target_if.h>
32 #include <qdf_module.h>
33 #include <wlan_reg_services_api.h>
34 #include <wlan_dfs_ucfg_api.h>
35 
36 /**
37  * @spectral_ops - Spectral function table, holds the Spectral functions that
38  * depend on whether the architecture is Direct Attach or Offload. This is used
39  * to populate the actual Spectral function table present in the Spectral
40  * module.
41  */
42 struct target_if_spectral_ops spectral_ops;
43 int spectral_debug_level = DEBUG_SPECTRAL;
44 struct spectral_tgt_ops ops_tgt;
45 
46 static void target_if_spectral_get_firstvdev_pdev(struct wlan_objmgr_pdev *pdev,
47 						  void *obj, void *arg)
48 {
49 	struct wlan_objmgr_vdev *vdev = obj;
50 	struct wlan_objmgr_vdev **first_vdev = arg;
51 
52 	if (!(*first_vdev))
53 		*first_vdev = vdev;
54 }
55 
56 struct wlan_objmgr_vdev *
57 target_if_spectral_get_vdev(struct target_if_spectral *spectral,
58 			    enum spectral_scan_mode smode)
59 {
60 	struct wlan_objmgr_pdev *pdev = NULL;
61 	struct wlan_objmgr_vdev *first_vdev = NULL;
62 
63 	qdf_assert_always(spectral);
64 	pdev = spectral->pdev_obj;
65 	qdf_assert_always(pdev);
66 
67 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
68 		spectral_err("Invalid Spectral mode %u", smode);
69 		return NULL;
70 	}
71 
72 	if (spectral->vdev_id[smode] != WLAN_INVALID_VDEV_ID) {
73 		first_vdev = wlan_objmgr_get_vdev_by_id_from_pdev(
74 						pdev, spectral->vdev_id[smode],
75 						WLAN_SPECTRAL_ID);
76 		return first_vdev;
77 	}
78 
79 	if (wlan_objmgr_pdev_try_get_ref(pdev, WLAN_SPECTRAL_ID) !=
80 	    QDF_STATUS_SUCCESS) {
81 		spectral_err("Unable to get pdev reference.");
82 		return NULL;
83 	}
84 
85 	wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
86 					  target_if_spectral_get_firstvdev_pdev,
87 					  &first_vdev, 0, WLAN_SPECTRAL_ID);
88 
89 	wlan_objmgr_pdev_release_ref(pdev, WLAN_SPECTRAL_ID);
90 
91 	if (!first_vdev)
92 		return NULL;
93 
94 	if (wlan_objmgr_vdev_try_get_ref(first_vdev, WLAN_SPECTRAL_ID) !=
95 			QDF_STATUS_SUCCESS)
96 		first_vdev = NULL;
97 
98 	return first_vdev;
99 }
100 
101 /**
102  * target_if_send_vdev_spectral_configure_cmd() - Send WMI command to configure
103  * spectral parameters
104  * @spectral: Pointer to Spectral target_if internal private data
105  * @smode: Spectral scan mode
106  * @param: Pointer to spectral_config giving the Spectral configuration
107  *
108  * Return: QDF_STATUS_SUCCESS on success, negative error code on failure
109  */
110 static int
111 target_if_send_vdev_spectral_configure_cmd(struct target_if_spectral *spectral,
112 					   enum spectral_scan_mode smode,
113 					   struct spectral_config *param)
114 {
115 	struct vdev_spectral_configure_params sparam;
116 	struct wlan_objmgr_psoc *psoc;
117 	struct wlan_objmgr_pdev *pdev = NULL;
118 	struct wlan_objmgr_vdev *vdev = NULL;
119 	struct target_if_psoc_spectral *psoc_spectral;
120 
121 	qdf_assert_always(spectral && param);
122 
123 	pdev = spectral->pdev_obj;
124 
125 	qdf_assert_always(pdev);
126 
127 	psoc = wlan_pdev_get_psoc(pdev);
128 	if (!psoc) {
129 		spectral_err("psoc is null");
130 		return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
131 	}
132 
133 	psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
134 	if (!psoc_spectral) {
135 		spectral_err("psoc spectral object is null");
136 		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
137 	}
138 
139 	vdev = target_if_spectral_get_vdev(spectral, smode);
140 	if (!vdev)
141 		return QDF_STATUS_E_NOENT;
142 
143 	qdf_mem_zero(&sparam, sizeof(sparam));
144 
145 	sparam.vdev_id = wlan_vdev_get_id(vdev);
146 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
147 
148 	sparam.count = param->ss_count;
149 	sparam.period = param->ss_period;
150 	sparam.spectral_pri = param->ss_spectral_pri;
151 	sparam.fft_size = param->ss_fft_size;
152 	sparam.gc_enable = param->ss_gc_ena;
153 	sparam.restart_enable = param->ss_restart_ena;
154 	sparam.noise_floor_ref = param->ss_noise_floor_ref;
155 	sparam.init_delay = param->ss_init_delay;
156 	sparam.nb_tone_thr = param->ss_nb_tone_thr;
157 	sparam.str_bin_thr = param->ss_str_bin_thr;
158 	sparam.wb_rpt_mode = param->ss_wb_rpt_mode;
159 	sparam.rssi_rpt_mode = param->ss_rssi_rpt_mode;
160 	sparam.rssi_thr = param->ss_rssi_thr;
161 	sparam.pwr_format = param->ss_pwr_format;
162 	sparam.rpt_mode = param->ss_rpt_mode;
163 	sparam.bin_scale = param->ss_bin_scale;
164 	sparam.dbm_adj = param->ss_dbm_adj;
165 	sparam.chn_mask = param->ss_chn_mask;
166 	sparam.mode = smode;
167 	sparam.center_freq1 = param->ss_frequency.cfreq1;
168 	sparam.center_freq2 = param->ss_frequency.cfreq2;
169 	sparam.chan_width = spectral->ch_width[smode];
170 
171 	return psoc_spectral->wmi_ops.wmi_spectral_configure_cmd_send(
172 				GET_WMI_HDL_FROM_PDEV(pdev), &sparam);
173 }
174 
175 /**
176  * target_if_send_vdev_spectral_enable_cmd() - Send WMI command to
177  * enable/disable Spectral
178  * @spectral: Pointer to Spectral target_if internal private data
179  * @smode: Spectral scan mode
180  * @is_spectral_active_valid: Flag to indicate if spectral activate (trigger) is
181  * valid
182  * @is_spectral_active: Value of spectral activate
183  * @is_spectral_enabled_valid: Flag to indicate if spectral enable is valid
184  * @is_spectral_enabled: Value of spectral enable
185  *
186  * Return: QDF_STATUS_SUCCESS on success, negative error code on failure
187  */
188 static int
189 target_if_send_vdev_spectral_enable_cmd(struct target_if_spectral *spectral,
190 					enum spectral_scan_mode smode,
191 					uint8_t is_spectral_active_valid,
192 					uint8_t is_spectral_active,
193 					uint8_t is_spectral_enabled_valid,
194 					uint8_t is_spectral_enabled)
195 {
196 	struct vdev_spectral_enable_params param;
197 	struct wlan_objmgr_psoc *psoc;
198 	struct wlan_objmgr_pdev *pdev = NULL;
199 	struct wlan_objmgr_vdev *vdev = NULL;
200 	struct target_if_psoc_spectral *psoc_spectral;
201 
202 	qdf_assert_always(spectral);
203 
204 	pdev = spectral->pdev_obj;
205 
206 	qdf_assert_always(pdev);
207 
208 	psoc = wlan_pdev_get_psoc(pdev);
209 	if (!psoc) {
210 		spectral_err("psoc is null");
211 		return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
212 	}
213 
214 	psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
215 	if (!psoc_spectral) {
216 		spectral_err("psoc spectral object is null");
217 		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
218 	}
219 
220 	vdev = target_if_spectral_get_vdev(spectral, smode);
221 	if (!vdev)
222 		return QDF_STATUS_E_NOENT;
223 
224 	qdf_mem_zero(&param, sizeof(param));
225 
226 	param.vdev_id = wlan_vdev_get_id(vdev);
227 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
228 
229 	param.active_valid = is_spectral_active_valid;
230 	param.enabled_valid = is_spectral_enabled_valid;
231 	param.active = is_spectral_active;
232 	param.enabled = is_spectral_enabled;
233 	param.mode = smode;
234 
235 	return psoc_spectral->wmi_ops.wmi_spectral_enable_cmd_send(
236 				GET_WMI_HDL_FROM_PDEV(pdev), &param);
237 }
238 
239 /**
240  * target_if_spectral_info_init_defaults() - Helper function to load defaults
241  * for Spectral information (parameters and state) into cache.
242  * @spectral: Pointer to Spectral target_if internal private data
243  * @smode: Spectral scan mode
244  *
245  * It is assumed that the caller has obtained the requisite lock if applicable.
246  * Note that this is currently treated as a temporary function.  Ideally, we
247  * would like to get defaults from the firmware.
248  *
249  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
250  */
251 static QDF_STATUS
252 target_if_spectral_info_init_defaults(struct target_if_spectral *spectral,
253 				      enum spectral_scan_mode smode)
254 {
255 	struct target_if_spectral_param_state_info *info;
256 	struct wlan_objmgr_vdev *vdev = NULL;
257 
258 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
259 		spectral_err("Invalid Spectral mode %u", smode);
260 		return QDF_STATUS_E_FAILURE;
261 	}
262 
263 	info = &spectral->param_info[smode];
264 
265 	/* State */
266 	info->osps_cache.osc_spectral_active = SPECTRAL_SCAN_ACTIVE_DEFAULT;
267 
268 	info->osps_cache.osc_spectral_enabled = SPECTRAL_SCAN_ENABLE_DEFAULT;
269 
270 	/* Parameters */
271 	info->osps_cache.osc_params.ss_count = SPECTRAL_SCAN_COUNT_DEFAULT;
272 
273 	if (spectral->spectral_gen == SPECTRAL_GEN3)
274 		info->osps_cache.osc_params.ss_period =
275 			SPECTRAL_SCAN_PERIOD_GEN_III_DEFAULT;
276 	else
277 		info->osps_cache.osc_params.ss_period =
278 			SPECTRAL_SCAN_PERIOD_GEN_II_DEFAULT;
279 
280 	info->osps_cache.osc_params.ss_spectral_pri =
281 	    SPECTRAL_SCAN_PRIORITY_DEFAULT;
282 
283 	info->osps_cache.osc_params.ss_fft_size =
284 	    SPECTRAL_SCAN_FFT_SIZE_DEFAULT;
285 
286 	info->osps_cache.osc_params.ss_gc_ena = SPECTRAL_SCAN_GC_ENA_DEFAULT;
287 
288 	info->osps_cache.osc_params.ss_restart_ena =
289 	    SPECTRAL_SCAN_RESTART_ENA_DEFAULT;
290 
291 	info->osps_cache.osc_params.ss_noise_floor_ref =
292 	    SPECTRAL_SCAN_NOISE_FLOOR_REF_DEFAULT;
293 
294 	info->osps_cache.osc_params.ss_init_delay =
295 	    SPECTRAL_SCAN_INIT_DELAY_DEFAULT;
296 
297 	info->osps_cache.osc_params.ss_nb_tone_thr =
298 	    SPECTRAL_SCAN_NB_TONE_THR_DEFAULT;
299 
300 	info->osps_cache.osc_params.ss_str_bin_thr =
301 	    SPECTRAL_SCAN_STR_BIN_THR_DEFAULT;
302 
303 	info->osps_cache.osc_params.ss_wb_rpt_mode =
304 	    SPECTRAL_SCAN_WB_RPT_MODE_DEFAULT;
305 
306 	info->osps_cache.osc_params.ss_rssi_rpt_mode =
307 	    SPECTRAL_SCAN_RSSI_RPT_MODE_DEFAULT;
308 
309 	info->osps_cache.osc_params.ss_rssi_thr =
310 	    SPECTRAL_SCAN_RSSI_THR_DEFAULT;
311 
312 	info->osps_cache.osc_params.ss_pwr_format =
313 	    SPECTRAL_SCAN_PWR_FORMAT_DEFAULT;
314 
315 	info->osps_cache.osc_params.ss_rpt_mode =
316 	    SPECTRAL_SCAN_RPT_MODE_DEFAULT;
317 
318 	info->osps_cache.osc_params.ss_bin_scale =
319 	    SPECTRAL_SCAN_BIN_SCALE_DEFAULT;
320 
321 	info->osps_cache.osc_params.ss_dbm_adj = SPECTRAL_SCAN_DBM_ADJ_DEFAULT;
322 
323 	vdev = target_if_spectral_get_vdev(spectral, smode);
324 	if (!vdev)
325 		return QDF_STATUS_E_NOENT;
326 
327 	info->osps_cache.osc_params.ss_chn_mask =
328 	    wlan_vdev_mlme_get_rxchainmask(vdev);
329 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
330 
331 	info->osps_cache.osc_params.ss_short_report =
332 		SPECTRAL_SCAN_SHORT_REPORT_DEFAULT;
333 
334 	info->osps_cache.osc_params.ss_fft_period =
335 		SPECTRAL_SCAN_FFT_PERIOD_DEFAULT;
336 
337 	info->osps_cache.osc_params.ss_frequency.cfreq1 =
338 		SPECTRAL_SCAN_FREQUENCY_DEFAULT;
339 	info->osps_cache.osc_params.ss_frequency.cfreq2 =
340 		SPECTRAL_SCAN_FREQUENCY_DEFAULT;
341 
342 	/* The cache is now valid */
343 	info->osps_cache.osc_is_valid = 1;
344 
345 	return QDF_STATUS_SUCCESS;
346 }
347 
348 /**
349  * target_if_log_read_spectral_active() - Helper function to log whether
350  * spectral is active after reading cache
351  * @function_name: Function name
352  * @output: whether spectral is active or not
353  *
354  * Helper function to log whether spectral is active after reading cache
355  *
356  * Return: none
357  */
358 static void
359 target_if_log_read_spectral_active(
360 	const char *function_name,
361 	unsigned char output)
362 {
363 	spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ACTIVE. Returning val=%u",
364 		       function_name, output);
365 }
366 
367 /**
368  * target_if_log_read_spectral_enabled() - Helper function to log whether
369  * spectral is enabled after reading cache
370  * @function_name: Function name
371  * @output: whether spectral is enabled or not
372  *
373  * Helper function to log whether spectral is enabled after reading cache
374  *
375  * Return: none
376  */
377 static void
378 target_if_log_read_spectral_enabled(
379 	const char *function_name,
380 	unsigned char output)
381 {
382 	spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ENABLED. Returning val=%u",
383 		       function_name, output);
384 }
385 
386 /**
387  * target_if_log_read_spectral_enabled() - Helper function to log spectral
388  * parameters after reading cache
389  * @function_name: Function name
390  * @pparam: Spectral parameters
391  *
392  * Helper function to log spectral parameters after reading cache
393  *
394  * Return: none
395  */
396 static void
397 target_if_log_read_spectral_params(
398 	const char *function_name,
399 	struct spectral_config *pparam)
400 {
401 	spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_PARAMS. Returning following params:\nss_count = %u\nss_period = %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",
402 		       function_name,
403 		       pparam->ss_count,
404 		       pparam->ss_period,
405 		       pparam->ss_spectral_pri,
406 		       pparam->ss_fft_size,
407 		       pparam->ss_gc_ena,
408 		       pparam->ss_restart_ena,
409 		       (int8_t)pparam->ss_noise_floor_ref,
410 		       pparam->ss_init_delay,
411 		       pparam->ss_nb_tone_thr,
412 		       pparam->ss_str_bin_thr,
413 		       pparam->ss_wb_rpt_mode,
414 		       pparam->ss_rssi_rpt_mode,
415 		       (int8_t)pparam->ss_rssi_thr,
416 		       pparam->ss_pwr_format,
417 		       pparam->ss_rpt_mode,
418 		       pparam->ss_bin_scale,
419 		       pparam->ss_dbm_adj,
420 		       pparam->ss_chn_mask,
421 		       pparam->ss_frequency.cfreq1,
422 		       pparam->ss_frequency.cfreq2);
423 }
424 
425 /**
426  * target_if_log_read_spectral_active_catch_validate() - Helper function to
427  * log whether spectral is active after intializing the cache
428  * @function_name: Function name
429  * @output: whether spectral is active or not
430  *
431  * Helper function to log whether spectral is active after intializing cache
432  *
433  * Return: none
434  */
435 static void
436 target_if_log_read_spectral_active_catch_validate(
437 	const char *function_name,
438 	unsigned char output)
439 {
440 	spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ACTIVE on initial cache validation\nReturning val=%u",
441 		       function_name, output);
442 }
443 
444 /**
445  * target_if_log_read_spectral_enabled_catch_validate() - Helper function to
446  * log whether spectral is enabled after intializing the cache
447  * @function_name: Function name
448  * @output: whether spectral is enabled or not
449  *
450  * Helper function to log whether spectral is enabled after intializing cache
451  *
452  * Return: none
453  */
454 static void
455 target_if_log_read_spectral_enabled_catch_validate(
456 	const char *function_name,
457 	unsigned char output)
458 {
459 	spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ENABLED on initial cache validation\nReturning val=%u\n",
460 		       function_name, output);
461 }
462 
463 /**
464  * target_if_log_read_spectral_params_catch_validate() - Helper function to
465  * log spectral parameters after intializing the cache
466  * @function_name: Function name
467  * @pparam: Spectral parameters
468  *
469  * Helper function to log spectral parameters after intializing the cache
470  *
471  * Return: none
472  */
473 static void
474 target_if_log_read_spectral_params_catch_validate(
475 	const char *function_name,
476 	struct spectral_config *pparam)
477 {
478 	spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_PARAMS on initial cache validation\nReturning following params:\nss_count = %u\nss_period = %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",
479 		       function_name,
480 		       pparam->ss_count,
481 		       pparam->ss_period,
482 		       pparam->ss_spectral_pri,
483 		       pparam->ss_fft_size,
484 		       pparam->ss_gc_ena,
485 		       pparam->ss_restart_ena,
486 		       (int8_t)pparam->ss_noise_floor_ref,
487 		       pparam->ss_init_delay,
488 		       pparam->ss_nb_tone_thr,
489 		       pparam->ss_str_bin_thr,
490 		       pparam->ss_wb_rpt_mode,
491 		       pparam->ss_rssi_rpt_mode,
492 		       (int8_t)pparam->ss_rssi_thr,
493 		       pparam->ss_pwr_format,
494 		       pparam->ss_rpt_mode,
495 		       pparam->ss_bin_scale,
496 		       pparam->ss_dbm_adj, pparam->ss_chn_mask);
497 }
498 
499 /**
500  * target_if_spectral_info_read() - Read spectral information from the cache.
501  * @spectral: Pointer to Spectral target_if internal private data
502  * @smode: Spectral scan mode
503  * @specifier: target_if_spectral_info enumeration specifying which
504  * information is required
505  * @output: Void output pointer into which the information will be read
506  * @output_len: size of object pointed to by output pointer
507  *
508  * Read spectral parameters or the desired state information from the cache.
509  *
510  * Return: 0 on success, negative error code on failure
511  */
512 static int
513 target_if_spectral_info_read(
514 	struct target_if_spectral *spectral,
515 	enum spectral_scan_mode smode,
516 	enum target_if_spectral_info specifier,
517 	void *output, int output_len)
518 {
519 	/*
520 	 * Note: This function is designed to be able to accommodate
521 	 * WMI reads for defaults, non-cacheable information, etc
522 	 * if required.
523 	 */
524 	struct target_if_spectral_param_state_info *info;
525 	int is_cacheable = 0;
526 	int init_def_retval = 0;
527 
528 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
529 		spectral_err("Invalid Spectral mode %u", smode);
530 		return -EINVAL;
531 	}
532 	info = &spectral->param_info[smode];
533 
534 	if (!output)
535 		return -EINVAL;
536 
537 	switch (specifier) {
538 	case TARGET_IF_SPECTRAL_INFO_ACTIVE:
539 		if (output_len != sizeof(info->osps_cache.osc_spectral_active))
540 			return -EINVAL;
541 		is_cacheable = 1;
542 		break;
543 
544 	case TARGET_IF_SPECTRAL_INFO_ENABLED:
545 		if (output_len != sizeof(info->osps_cache.osc_spectral_enabled))
546 			return -EINVAL;
547 		is_cacheable = 1;
548 		break;
549 
550 	case TARGET_IF_SPECTRAL_INFO_PARAMS:
551 		if (output_len != sizeof(info->osps_cache.osc_params))
552 			return -EINVAL;
553 		is_cacheable = 1;
554 		break;
555 
556 	default:
557 		spectral_err("Unknown target_if_spectral_info specifier");
558 		return -EINVAL;
559 	}
560 
561 	qdf_spin_lock(&info->osps_lock);
562 
563 	if (is_cacheable) {
564 		if (info->osps_cache.osc_is_valid) {
565 			switch (specifier) {
566 			case TARGET_IF_SPECTRAL_INFO_ACTIVE:
567 				qdf_mem_copy(
568 				  output,
569 				  &info->osps_cache.osc_spectral_active,
570 				  sizeof(info->osps_cache.osc_spectral_active));
571 
572 				target_if_log_read_spectral_active(
573 					__func__,
574 					*((unsigned char *)output));
575 				break;
576 
577 			case TARGET_IF_SPECTRAL_INFO_ENABLED:
578 				qdf_mem_copy(
579 				  output,
580 				  &info->osps_cache.osc_spectral_enabled,
581 				  sizeof(
582 					info->osps_cache.osc_spectral_enabled));
583 
584 				target_if_log_read_spectral_enabled(
585 					__func__,
586 					*((unsigned char *)output));
587 				break;
588 
589 			case TARGET_IF_SPECTRAL_INFO_PARAMS:
590 				qdf_mem_copy(
591 				  output,
592 				  &info->osps_cache.osc_params,
593 				  sizeof(info->osps_cache.osc_params));
594 
595 				target_if_log_read_spectral_params(
596 					__func__,
597 					(struct spectral_config *)output);
598 				break;
599 
600 			default:
601 				/* We can't reach this point */
602 				break;
603 			}
604 			qdf_spin_unlock(&info->osps_lock);
605 			return 0;
606 		}
607 	}
608 
609 	/* Cache is invalid */
610 
611 	/*
612 	 * If WMI Reads are implemented to fetch defaults/non-cacheable info,
613 	 * then the below implementation will change
614 	 */
615 	init_def_retval =
616 			target_if_spectral_info_init_defaults(spectral, smode);
617 	if (init_def_retval != QDF_STATUS_SUCCESS) {
618 		qdf_spin_unlock(&info->osps_lock);
619 		if (init_def_retval == QDF_STATUS_E_NOENT)
620 			return -ENOENT;
621 		else
622 			return -EINVAL;
623 	}
624 	/* target_if_spectral_info_init_defaults() has set cache to valid */
625 
626 	switch (specifier) {
627 	case TARGET_IF_SPECTRAL_INFO_ACTIVE:
628 		qdf_mem_copy(output,
629 			     &info->osps_cache.osc_spectral_active,
630 			     sizeof(info->osps_cache.osc_spectral_active));
631 
632 		target_if_log_read_spectral_active_catch_validate(
633 			__func__,
634 			*((unsigned char *)output));
635 		break;
636 
637 	case TARGET_IF_SPECTRAL_INFO_ENABLED:
638 		qdf_mem_copy(output,
639 			     &info->osps_cache.osc_spectral_enabled,
640 			     sizeof(info->osps_cache.osc_spectral_enabled));
641 
642 		target_if_log_read_spectral_enabled_catch_validate(
643 			__func__,
644 			*((unsigned char *)output));
645 		break;
646 
647 	case TARGET_IF_SPECTRAL_INFO_PARAMS:
648 		qdf_mem_copy(output,
649 			     &info->osps_cache.osc_params,
650 			     sizeof(info->osps_cache.osc_params));
651 
652 		target_if_log_read_spectral_params_catch_validate(
653 			__func__,
654 			(struct spectral_config *)output);
655 
656 		break;
657 
658 	default:
659 		/* We can't reach this point */
660 		break;
661 	}
662 
663 	qdf_spin_unlock(&info->osps_lock);
664 
665 	return 0;
666 }
667 
668 /**
669  * target_if_log_write_spectral_active() - Helper function to log inputs and
670  * return value of call to configure the Spectral 'active' configuration,
671  * TARGET_IF_SPECTRAL_INFO_ACTIVE into firmware
672  * @function_name: Function name in which this is called
673  * @pval: whether spectral is active or not
674  * @ret: return value of the firmware write function
675  *
676  * Return: none
677  */
678 static void
679 target_if_log_write_spectral_active(
680 	const char *function_name,
681 	uint8_t pval,
682 	int ret)
683 {
684 	spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ACTIVE with val=%u status=%d",
685 		       function_name, pval, ret);
686 }
687 
688 /**
689  * target_if_log_write_spectral_enabled() - Helper function to log inputs and
690  * return value of call to configure the Spectral 'enabled' configuration,
691  * TARGET_IF_SPECTRAL_INFO_ENABLED into firmware
692  * @function_name: Function name in which this is called
693  * @pval: whether spectral is enabled or not
694  * @ret: return value of the firmware write function
695  *
696  * Return: none
697  */
698 static void
699 target_if_log_write_spectral_enabled(
700 	const char *function_name,
701 	uint8_t pval,
702 	int ret)
703 {
704 	spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ENABLED with val=%u status=%d",
705 		       function_name, pval, ret);
706 }
707 
708 /**
709  * target_if_log_write_spectral_params() - Helper function to log inputs and
710  * return value of call to configure Spectral parameters,
711  * TARGET_IF_SPECTRAL_INFO_PARAMS into firmware
712  * @param: Spectral parameters
713  * @function_name: Function name in which this is called
714  * @ret: return value of the firmware write function
715  *
716  * Return: none
717  */
718 static void
719 target_if_log_write_spectral_params(
720 	struct spectral_config *param,
721 	const char *function_name,
722 	int ret)
723 {
724 	spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_PARAMS. Params:\nss_count = %u\nss_period = %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",
725 		       function_name,
726 		       param->ss_count,
727 		       param->ss_period,
728 		       param->ss_spectral_pri,
729 		       param->ss_fft_size,
730 		       param->ss_gc_ena,
731 		       param->ss_restart_ena,
732 		       (int8_t)param->ss_noise_floor_ref,
733 		       param->ss_init_delay,
734 		       param->ss_nb_tone_thr,
735 		       param->ss_str_bin_thr,
736 		       param->ss_wb_rpt_mode,
737 		       param->ss_rssi_rpt_mode,
738 		       (int8_t)param->ss_rssi_thr,
739 		       param->ss_pwr_format,
740 		       param->ss_rpt_mode,
741 		       param->ss_bin_scale,
742 		       param->ss_dbm_adj,
743 		       param->ss_chn_mask,
744 		       param->ss_frequency.cfreq1,
745 		       param->ss_frequency.cfreq2,
746 		       ret);
747 }
748 
749 /**
750  * target_if_spectral_info_write() - Write Spectral information to the
751  * firmware, and update cache
752  * @spectral: Pointer to Spectral target_if internal private data
753  * @smode: Spectral scan mode
754  * @specifier: target_if_spectral_info enumeration specifying which
755  * information is involved
756  * @input: void input pointer containing the information to be written
757  * @input_len: size of object pointed to by input pointer
758  *
759  * Write Spectral parameters or the desired state information to
760  * the firmware, and update cache
761  *
762  * Return: 0 on success, negative error code on failure
763  */
764 static int
765 target_if_spectral_info_write(
766 	struct target_if_spectral *spectral,
767 	enum spectral_scan_mode smode,
768 	enum target_if_spectral_info specifier,
769 	void *input, int input_len)
770 {
771 	struct target_if_spectral_param_state_info *info;
772 	int ret;
773 	uint8_t *pval = NULL;
774 	struct spectral_config *param = NULL;
775 
776 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
777 		spectral_err("Invalid Spectral mode %u", smode);
778 		return -EINVAL;
779 	}
780 	info = &spectral->param_info[smode];
781 
782 	if (!input)
783 		return -EINVAL;
784 
785 	switch (specifier) {
786 	case TARGET_IF_SPECTRAL_INFO_ACTIVE:
787 		if (input_len != sizeof(info->osps_cache.osc_spectral_active))
788 			return -EINVAL;
789 
790 		pval = (uint8_t *)input;
791 
792 		qdf_spin_lock(&info->osps_lock);
793 		ret = target_if_send_vdev_spectral_enable_cmd(spectral, smode,
794 							      1, *pval, 0, 0);
795 
796 		target_if_log_write_spectral_active(
797 			__func__,
798 			*pval,
799 			ret);
800 
801 		if (ret < 0) {
802 			spectral_err("target_if_send_vdev_spectral_enable_cmd failed with error=%d",
803 				     ret);
804 			qdf_spin_unlock(&info->osps_lock);
805 			return ret;
806 		}
807 
808 		info->osps_cache.osc_spectral_active = *pval;
809 
810 		/* The cache is now valid */
811 		info->osps_cache.osc_is_valid = 1;
812 
813 		qdf_spin_unlock(&info->osps_lock);
814 		break;
815 
816 	case TARGET_IF_SPECTRAL_INFO_ENABLED:
817 		if (input_len != sizeof(info->osps_cache.osc_spectral_enabled))
818 			return -EINVAL;
819 
820 		pval = (uint8_t *)input;
821 
822 		qdf_spin_lock(&info->osps_lock);
823 		ret = target_if_send_vdev_spectral_enable_cmd(spectral, smode,
824 							      0, 0, 1, *pval);
825 
826 		target_if_log_write_spectral_enabled(
827 			__func__,
828 			*pval,
829 			ret);
830 
831 		if (ret < 0) {
832 			spectral_err("target_if_send_vdev_spectral_enable_cmd failed with error=%d",
833 				     ret);
834 			qdf_spin_unlock(&info->osps_lock);
835 			return ret;
836 		}
837 
838 		info->osps_cache.osc_spectral_enabled = *pval;
839 
840 		/* The cache is now valid */
841 		info->osps_cache.osc_is_valid = 1;
842 
843 		qdf_spin_unlock(&info->osps_lock);
844 		break;
845 
846 	case TARGET_IF_SPECTRAL_INFO_PARAMS:
847 		if (input_len != sizeof(info->osps_cache.osc_params))
848 			return -EINVAL;
849 
850 		param = (struct spectral_config *)input;
851 
852 		qdf_spin_lock(&info->osps_lock);
853 		ret = target_if_send_vdev_spectral_configure_cmd(spectral,
854 								 smode, param);
855 
856 		target_if_log_write_spectral_params(
857 			param,
858 			__func__,
859 			ret);
860 
861 		if (ret < 0) {
862 			spectral_err("target_if_send_vdev_spectral_configure_cmd failed with error=%d",
863 				     ret);
864 			qdf_spin_unlock(&info->osps_lock);
865 			return ret;
866 		}
867 
868 		qdf_mem_copy(&info->osps_cache.osc_params,
869 			     param, sizeof(info->osps_cache.osc_params));
870 
871 		/* The cache is now valid */
872 		info->osps_cache.osc_is_valid = 1;
873 
874 		qdf_spin_unlock(&info->osps_lock);
875 		break;
876 
877 	default:
878 		spectral_err("Unknown target_if_spectral_info specifier");
879 		return -EINVAL;
880 	}
881 
882 	return 0;
883 }
884 
885 /**
886  * target_if_spectral_get_tsf64() - Function to get the TSF value
887  * @arg: Pointer to handle for Spectral target_if internal private data
888  *
889  * Get the last TSF received in WMI buffer
890  *
891  * Return: TSF value
892  */
893 static uint64_t
894 target_if_spectral_get_tsf64(void *arg)
895 {
896 	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
897 
898 	return spectral->tsf64;
899 }
900 
901 /**
902  * target_if_spectral_get_capability() - Function to get whether a
903  * given Spectral hardware capability is available
904  * @arg: Pointer to handle for Spectral target_if internal private data
905  * @type: Spectral hardware capability type
906  *
907  * Get whether a given Spectral hardware capability is available
908  *
909  * Return: True if the capability is available, false if the capability is not
910  * available
911  */
912 uint32_t
913 target_if_spectral_get_capability(void *arg, enum spectral_capability_type type)
914 {
915 	int status = STATUS_FAIL;
916 
917 	switch (type) {
918 	case SPECTRAL_CAP_PHYDIAG:
919 	case SPECTRAL_CAP_RADAR:
920 	case SPECTRAL_CAP_SPECTRAL_SCAN:
921 	case SPECTRAL_CAP_ADVNCD_SPECTRAL_SCAN:
922 		status = STATUS_PASS;
923 		break;
924 	default:
925 		status = STATUS_FAIL;
926 	}
927 	return status;
928 }
929 
930 /**
931  * target_if_spectral_set_rxfilter() - Set the RX Filter before Spectral start
932  * @arg: Pointer to handle for Spectral target_if internal private data
933  * @rxfilter: Rx filter to be used
934  *
935  * Note: This is only a placeholder function. It is not currently required since
936  * FW should be taking care of setting the required filters.
937  *
938  * Return: 0
939  */
940 uint32_t
941 target_if_spectral_set_rxfilter(void *arg, int rxfilter)
942 {
943 	/*
944 	 * Will not be required since enabling of spectral in firmware
945 	 * will take care of this
946 	 */
947 	return 0;
948 }
949 
950 /**
951  * target_if_spectral_get_rxfilter() - Get the current RX Filter settings
952  * @arg: Pointer to handle for Spectral target_if internal private data
953  *
954  * Note: This is only a placeholder function. It is not currently required since
955  * FW should be taking care of setting the required filters.
956  *
957  * Return: 0
958  */
959 uint32_t
960 target_if_spectral_get_rxfilter(void *arg)
961 {
962 	/*
963 	 * Will not be required since enabling of spectral in firmware
964 	 * will take care of this
965 	 */
966 	return 0;
967 }
968 
969 /**
970  * target_if_sops_is_spectral_active() - Get whether Spectral is active
971  * @arg: Pointer to handle for Spectral target_if internal private data
972  * @smode: Spectral scan mode
973  *
974  * Function to check whether Spectral is active
975  *
976  * Return: True if Spectral is active, false if Spectral is not active
977  */
978 uint32_t
979 target_if_sops_is_spectral_active(void *arg, enum spectral_scan_mode smode)
980 {
981 	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
982 	uint8_t val = 0;
983 	int ret;
984 
985 	ret = target_if_spectral_info_read(
986 		spectral,
987 		smode,
988 		TARGET_IF_SPECTRAL_INFO_ACTIVE,
989 		&val, sizeof(val));
990 
991 	if (ret != 0) {
992 		/*
993 		 * Could not determine if Spectral is active.
994 		 * Return false as a safe value.
995 		 * XXX: Consider changing the function prototype
996 		 * to be able to indicate failure to fetch value.
997 		 */
998 		return 0;
999 	}
1000 
1001 	return val;
1002 }
1003 
1004 /**
1005  * target_if_sops_is_spectral_enabled() - Get whether Spectral is enabled
1006  * @arg: Pointer to handle for Spectral target_if internal private data
1007  * @smode: Spectral scan mode
1008  *
1009  * Function to check whether Spectral is enabled
1010  *
1011  * Return: True if Spectral is enabled, false if Spectral is not enabled
1012  */
1013 uint32_t
1014 target_if_sops_is_spectral_enabled(void *arg, enum spectral_scan_mode smode)
1015 {
1016 	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
1017 	uint8_t val = 0;
1018 	int ret;
1019 
1020 	ret = target_if_spectral_info_read(
1021 		spectral,
1022 		smode,
1023 		TARGET_IF_SPECTRAL_INFO_ENABLED,
1024 		&val, sizeof(val));
1025 
1026 	if (ret != 0) {
1027 		/*
1028 		 * Could not determine if Spectral is enabled.
1029 		 * Return false as a safe value.
1030 		 * XXX: Consider changing the function prototype
1031 		 * to be able to indicate failure to fetch value.
1032 		 */
1033 		return 0;
1034 	}
1035 
1036 	return val;
1037 }
1038 
1039 /**
1040  * target_if_sops_start_spectral_scan() - Start Spectral scan
1041  * @arg: Pointer to handle for Spectral target_if internal private data
1042  * @smode: Spectral scan mode
1043  * @err: Spectral error code
1044  *
1045  * Function to start spectral scan
1046  *
1047  * Return: 0 on success else failure
1048  */
1049 uint32_t
1050 target_if_sops_start_spectral_scan(void *arg, enum spectral_scan_mode smode,
1051 				   enum spectral_cp_error_code *err)
1052 {
1053 	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
1054 	uint8_t val = 1;
1055 	uint8_t enabled = 0;
1056 	int ret;
1057 
1058 	ret = target_if_spectral_info_read(
1059 		spectral,
1060 		smode,
1061 		TARGET_IF_SPECTRAL_INFO_ENABLED,
1062 		&enabled, sizeof(enabled));
1063 
1064 	if (ret != 0) {
1065 		/*
1066 		 * Could not determine if Spectral is enabled. Assume we need
1067 		 * to enable it
1068 		 */
1069 		enabled = 0;
1070 	}
1071 
1072 	if (!enabled) {
1073 		ret = target_if_spectral_info_write(
1074 			spectral,
1075 			smode,
1076 			TARGET_IF_SPECTRAL_INFO_ENABLED,
1077 			&val, sizeof(val));
1078 
1079 		if (ret != 0)
1080 			return ret;
1081 	}
1082 
1083 	ret = target_if_spectral_info_write(
1084 		spectral,
1085 		smode,
1086 		TARGET_IF_SPECTRAL_INFO_ACTIVE,
1087 		&val, sizeof(val));
1088 
1089 	if (ret != 0)
1090 		return ret;
1091 
1092 	return 0;
1093 }
1094 
1095 /**
1096  * target_if_sops_stop_spectral_scan() - Stop Spectral scan
1097  * @arg: Pointer to handle for Spectral target_if internal private data
1098  * @smode: Spectral scan mode
1099  *
1100  * Function to stop spectral scan
1101  *
1102  * Return: 0 on success else failure
1103  */
1104 uint32_t
1105 target_if_sops_stop_spectral_scan(void *arg, enum spectral_scan_mode smode)
1106 {
1107 	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
1108 	uint8_t val = 0;
1109 	int tempret, ret = 0;
1110 	uint8_t enabled = 0;
1111 
1112 	tempret = target_if_spectral_info_read(
1113 		spectral,
1114 		smode,
1115 		TARGET_IF_SPECTRAL_INFO_ENABLED,
1116 		&enabled, sizeof(enabled));
1117 
1118 	if (tempret)
1119 		/*
1120 		 * Could not determine if Spectral is enabled. Assume scan is
1121 		 * not in progress
1122 		 */
1123 		enabled = 0;
1124 
1125 	/* if scan is not enabled, no need to send stop to FW */
1126 	if (!enabled)
1127 		return -EPERM;
1128 
1129 	tempret = target_if_spectral_info_write(
1130 			spectral,
1131 			smode,
1132 			TARGET_IF_SPECTRAL_INFO_ACTIVE,
1133 			&val, sizeof(val));
1134 
1135 	if (tempret != 0)
1136 		ret = tempret;
1137 
1138 	tempret = target_if_spectral_info_write(
1139 			spectral,
1140 			smode,
1141 			TARGET_IF_SPECTRAL_INFO_ENABLED,
1142 			&val, sizeof(val));
1143 
1144 	if (tempret != 0)
1145 		ret = tempret;
1146 
1147 	return ret;
1148 }
1149 
1150 /**
1151  * target_if_spectral_get_extension_channel() - Get the Extension channel
1152  * @arg: Pointer to handle for Spectral target_if internal private data
1153  * @smode: Spectral scan mode
1154  *
1155  * Function to get the current Extension channel (in MHz)
1156  *
1157  * Return: Current Extension channel (in MHz) on success, 0 on failure or if
1158  * extension channel is not present.
1159  */
1160 uint32_t
1161 target_if_spectral_get_extension_channel(void *arg,
1162 					 enum spectral_scan_mode smode)
1163 {
1164 	/*
1165 	 * XXX: Once we expand to use cases where Spectral could be activated
1166 	 * without a channel being set to VDEV, we need to consider returning a
1167 	 * negative value in case of failure and having all callers handle this.
1168 	 */
1169 
1170 	struct target_if_spectral *spectral = NULL;
1171 	struct wlan_objmgr_vdev *vdev = NULL;
1172 	uint16_t sec20chan_freq = 0;
1173 
1174 	qdf_assert_always(arg);
1175 	spectral = (struct target_if_spectral *)arg;
1176 
1177 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
1178 		spectral_err("Invalid Spectral mode %u", smode);
1179 		return 0;
1180 	}
1181 	vdev = target_if_spectral_get_vdev(spectral, smode);
1182 	if (!vdev)
1183 		return 0;
1184 
1185 	if (target_if_vdev_get_sec20chan_freq_mhz(vdev, &sec20chan_freq) < 0) {
1186 		wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
1187 		return 0;
1188 	}
1189 
1190 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
1191 
1192 	return sec20chan_freq;
1193 }
1194 
1195 /**
1196  * target_if_spectral_get_current_channel() - Get the current channel
1197  * @arg: Pointer to handle for Spectral target_if internal private data
1198  * @smode: Spectral scan mode
1199  *
1200  * Function to get the current channel (in MHz)
1201  *
1202  * Return: Current channel (in MHz) on success, 0 on failure
1203  */
1204 uint32_t
1205 target_if_spectral_get_current_channel(void *arg, enum spectral_scan_mode smode)
1206 {
1207 	/*
1208 	 * XXX: Once we expand to use cases where Spectral could be activated
1209 	 * without a channel being set to VDEV, we need to consider returning a
1210 	 * negative value in case of failure and having all callers handle this.
1211 	 */
1212 
1213 	struct target_if_spectral *spectral = NULL;
1214 	int16_t chan_freq = 0;
1215 	struct wlan_objmgr_vdev *vdev = NULL;
1216 
1217 	qdf_assert_always(arg);
1218 	spectral = (struct target_if_spectral *)arg;
1219 
1220 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
1221 		spectral_err("Invalid Spectral mode %u", smode);
1222 		return 0;
1223 	}
1224 	vdev = target_if_spectral_get_vdev(spectral, smode);
1225 	if (!vdev)
1226 		return 0;
1227 
1228 	chan_freq = target_if_vdev_get_chan_freq(vdev);
1229 	if (chan_freq < 0) {
1230 		wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
1231 		return 0;
1232 	}
1233 
1234 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
1235 
1236 	return chan_freq;
1237 }
1238 
1239 /**
1240  * target_if_spectral_reset_hw() - Reset the hardware
1241  * @arg: Pointer to handle for Spectral target_if internal private data
1242  *
1243  * This is only a placeholder since it is not currently required in the offload
1244  * case.
1245  *
1246  * Return: 0
1247  */
1248 uint32_t
1249 target_if_spectral_reset_hw(void *arg)
1250 {
1251 	not_yet_implemented();
1252 	return 0;
1253 }
1254 
1255 /**
1256  * target_if_spectral_get_chain_noise_floor() - Get the Chain noise floor from
1257  * Noisefloor history buffer
1258  * @arg: Pointer to handle for Spectral target_if internal private data
1259  * @nf_buf: Pointer to buffer into which chain Noise Floor data should be copied
1260  *
1261  * This is only a placeholder since it is not currently required in the offload
1262  * case.
1263  *
1264  * Return: 0
1265  */
1266 uint32_t
1267 target_if_spectral_get_chain_noise_floor(void *arg, int16_t *nf_buf)
1268 {
1269 	not_yet_implemented();
1270 	return 0;
1271 }
1272 
1273 /**
1274  * target_if_spectral_get_ext_noisefloor() - Get the extension channel
1275  * noisefloor
1276  * @arg: Pointer to handle for Spectral target_if internal private data
1277  *
1278  * This is only a placeholder since it is not currently required in the offload
1279  * case.
1280  *
1281  * Return: 0
1282  */
1283 int8_t
1284 target_if_spectral_get_ext_noisefloor(void *arg)
1285 {
1286 	not_yet_implemented();
1287 	return 0;
1288 }
1289 
1290 /**
1291  * target_if_spectral_get_ctl_noisefloor() - Get the control channel noisefloor
1292  * @arg: Pointer to handle for Spectral target_if internal private data
1293  *
1294  * This is only a placeholder since it is not currently required in the offload
1295  * case.
1296  *
1297  * Return: 0
1298  */
1299 int8_t
1300 target_if_spectral_get_ctl_noisefloor(void *arg)
1301 {
1302 	not_yet_implemented();
1303 	return 0;
1304 }
1305 
1306 /**
1307  * target_if_spectral_sops_configure_params() - Configure user supplied Spectral
1308  *                                         parameters
1309  * @arg: Pointer to handle for Spectral target_if internal private data
1310  * @params: Spectral parameters
1311  * @smode: Spectral scan mode
1312  *
1313  * Function to configure spectral parameters
1314  *
1315  * Return: 0 on success else failure
1316  */
1317 uint32_t
1318 target_if_spectral_sops_configure_params(
1319 	void *arg, struct spectral_config *params,
1320 	enum spectral_scan_mode smode)
1321 {
1322 	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
1323 
1324 	return target_if_spectral_info_write(
1325 		spectral,
1326 		smode,
1327 		TARGET_IF_SPECTRAL_INFO_PARAMS,
1328 		params, sizeof(*params));
1329 }
1330 
1331 /**
1332  * target_if_spectral_sops_get_params() - Get user configured Spectral
1333  * parameters
1334  * @arg: Pointer to handle for Spectral target_if internal private data
1335  * @params: Pointer to buffer into which Spectral parameters should be copied
1336  * @smode: Spectral scan mode
1337  *
1338  * Function to get the configured spectral parameters
1339  *
1340  * Return: 0 on success else failure
1341  */
1342 uint32_t
1343 target_if_spectral_sops_get_params(void *arg, struct spectral_config *params,
1344 				   enum spectral_scan_mode smode)
1345 {
1346 	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
1347 
1348 	return target_if_spectral_info_read(
1349 		spectral,
1350 		smode,
1351 		TARGET_IF_SPECTRAL_INFO_PARAMS,
1352 		params, sizeof(*params));
1353 }
1354 
1355 /**
1356  * target_if_spectral_get_ent_mask() - Get enterprise mask
1357  * @arg: Pointer to handle for Spectral target_if internal private data
1358  *
1359  * This is only a placeholder since it is not currently required in the offload
1360  * case.
1361  *
1362  * Return: 0
1363  */
1364 static uint32_t
1365 target_if_spectral_get_ent_mask(void *arg)
1366 {
1367 	not_yet_implemented();
1368 	return 0;
1369 }
1370 
1371 /**
1372  * target_if_spectral_get_macaddr() - Get radio MAC address
1373  * @arg: Pointer to handle for Spectral target_if internal private data
1374  * @addr: Pointer to buffer into which MAC address should be copied
1375  *
1376  * Function to get the MAC address of the pdev
1377  *
1378  * Return: 0 on success, -1 on failure
1379  */
1380 static uint32_t
1381 target_if_spectral_get_macaddr(void *arg, char *addr)
1382 {
1383 	uint8_t *myaddr = NULL;
1384 	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
1385 	struct wlan_objmgr_pdev *pdev = NULL;
1386 
1387 	pdev = spectral->pdev_obj;
1388 
1389 	wlan_pdev_obj_lock(pdev);
1390 	myaddr = wlan_pdev_get_hw_macaddr(pdev);
1391 	wlan_pdev_obj_unlock(pdev);
1392 	qdf_mem_copy(addr, myaddr, QDF_MAC_ADDR_SIZE);
1393 
1394 	return 0;
1395 }
1396 
1397 /**
1398  * target_if_init_spectral_param_min_max() - Initialize Spectral parameter
1399  * min and max values
1400  *
1401  * @param_min_max: Pointer to Spectral parameter min and max structure
1402  * @gen: Spectral HW generation
1403  * @target_type: Target type
1404  *
1405  * Initialize Spectral parameter min and max values
1406  *
1407  * Return: QDF_STATUS
1408  */
1409 static QDF_STATUS
1410 target_if_init_spectral_param_min_max(
1411 				struct spectral_param_min_max *param_min_max,
1412 				enum spectral_gen gen, uint32_t target_type)
1413 {
1414 	switch (gen) {
1415 	case SPECTRAL_GEN3:
1416 		param_min_max->fft_size_min = SPECTRAL_PARAM_FFT_SIZE_MIN_GEN3;
1417 		param_min_max->fft_size_max[CH_WIDTH_20MHZ] =
1418 				SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT;
1419 		if (target_type == TARGET_TYPE_QCN9000 ||
1420 		    target_type == TARGET_TYPE_QCA5018 ||
1421 		    target_type == TARGET_TYPE_QCA6490) {
1422 			param_min_max->fft_size_max[CH_WIDTH_40MHZ] =
1423 				SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000;
1424 			param_min_max->fft_size_max[CH_WIDTH_80MHZ] =
1425 				SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000;
1426 			param_min_max->fft_size_max[CH_WIDTH_160MHZ] =
1427 				SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000;
1428 			param_min_max->fft_size_max[CH_WIDTH_80P80MHZ] =
1429 				SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000;
1430 		} else {
1431 			param_min_max->fft_size_max[CH_WIDTH_40MHZ] =
1432 				SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT;
1433 			param_min_max->fft_size_max[CH_WIDTH_80MHZ] =
1434 				SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT;
1435 			param_min_max->fft_size_max[CH_WIDTH_160MHZ] =
1436 				SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT;
1437 			param_min_max->fft_size_max[CH_WIDTH_80P80MHZ] =
1438 				SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT;
1439 		}
1440 		break;
1441 
1442 	case SPECTRAL_GEN2:
1443 		param_min_max->fft_size_min = SPECTRAL_PARAM_FFT_SIZE_MIN_GEN2;
1444 		param_min_max->fft_size_max[CH_WIDTH_20MHZ] =
1445 					SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2;
1446 		param_min_max->fft_size_max[CH_WIDTH_40MHZ] =
1447 					SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2;
1448 		param_min_max->fft_size_max[CH_WIDTH_80MHZ] =
1449 					SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2;
1450 		param_min_max->fft_size_max[CH_WIDTH_80P80MHZ] =
1451 					SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2;
1452 		param_min_max->fft_size_max[CH_WIDTH_160MHZ] =
1453 					SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2;
1454 		break;
1455 
1456 	default:
1457 		spectral_err("Invalid spectral generation %d", gen);
1458 		return QDF_STATUS_E_INVAL;
1459 	}
1460 
1461 	return QDF_STATUS_SUCCESS;
1462 }
1463 
1464 /**
1465  * target_if_init_spectral_param_properties() - Initialize Spectral parameter
1466  *                                              properties
1467  * @spectral: Pointer to Spectral target_if internal private data
1468  *
1469  * Initialize Spectral parameter properties
1470  *
1471  * Return: QDF_STATUS
1472  */
1473 static QDF_STATUS
1474 target_if_init_spectral_param_properties(struct target_if_spectral *spectral)
1475 {
1476 	enum spectral_scan_mode smode = SPECTRAL_SCAN_MODE_NORMAL;
1477 	int param;
1478 
1479 	/* Initialize default values for properties.
1480 	 * Default values are supported for all the parameters for all modes
1481 	 * and allows different values for each mode for all the parameters .
1482 	 */
1483 	for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) {
1484 		for (param = 0; param < SPECTRAL_PARAM_MAX; param++) {
1485 			spectral->properties[smode][param].supported = true;
1486 			spectral->properties[smode][param].common_all_modes =
1487 									false;
1488 		}
1489 	}
1490 
1491 	/* Once FW advertisement is in place remove this hard coding */
1492 	smode = SPECTRAL_SCAN_MODE_NORMAL;
1493 	spectral->properties[SPECTRAL_SCAN_MODE_NORMAL]
1494 			[SPECTRAL_PARAM_FREQUENCY].supported = false;
1495 	for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) {
1496 		spectral->properties[smode]
1497 			[SPECTRAL_PARAM_SPECT_PRI].common_all_modes = true;
1498 		spectral->properties[smode]
1499 			[SPECTRAL_PARAM_SCAN_PERIOD].common_all_modes = true;
1500 		spectral->properties[smode]
1501 			[SPECTRAL_PARAM_INIT_DELAY].common_all_modes = true;
1502 	}
1503 
1504 	return QDF_STATUS_SUCCESS;
1505 }
1506 
1507 QDF_STATUS
1508 target_if_init_spectral_capability(struct target_if_spectral *spectral,
1509 				   uint32_t target_type)
1510 {
1511 	struct wlan_objmgr_psoc *psoc;
1512 	struct wlan_objmgr_pdev *pdev;
1513 	struct wlan_psoc_host_spectral_scaling_params *scaling_params;
1514 	uint8_t num_bin_scaling_params, param_idx, pdev_id;
1515 	struct target_psoc_info *tgt_psoc_info;
1516 	struct wlan_psoc_host_service_ext_param *ext_svc_param;
1517 	struct spectral_caps *pcap = &spectral->capability;
1518 	struct wlan_psoc_host_mac_phy_caps *mac_phy_cap_arr = NULL;
1519 	struct wlan_psoc_host_mac_phy_caps *mac_phy_cap = NULL;
1520 	struct wlan_psoc_host_chainmask_table *table;
1521 	int j;
1522 	uint32_t table_id;
1523 
1524 	pdev = spectral->pdev_obj;
1525 	psoc = wlan_pdev_get_psoc(pdev);
1526 	if (!psoc) {
1527 		spectral_err("psoc is null");
1528 		return QDF_STATUS_E_FAILURE;
1529 	}
1530 
1531 	tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc);
1532 	if (!tgt_psoc_info) {
1533 		spectral_err("target_psoc_info is null");
1534 		return QDF_STATUS_E_FAILURE;
1535 	}
1536 
1537 	ext_svc_param = target_psoc_get_service_ext_param(tgt_psoc_info);
1538 	num_bin_scaling_params = ext_svc_param->num_bin_scaling_params;
1539 	scaling_params = target_psoc_get_spectral_scaling_params(tgt_psoc_info);
1540 	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
1541 
1542 	/* XXX : Workaround: Set Spectral capability */
1543 	pcap = &spectral->capability;
1544 	pcap->phydiag_cap = 1;
1545 	pcap->radar_cap = 1;
1546 	pcap->spectral_cap = 1;
1547 	pcap->advncd_spectral_cap = 1;
1548 	pcap->hw_gen = spectral->spectral_gen;
1549 	if (spectral->spectral_gen >= SPECTRAL_GEN3) {
1550 		mac_phy_cap_arr = target_psoc_get_mac_phy_cap(tgt_psoc_info);
1551 		if (!mac_phy_cap_arr) {
1552 			spectral_err("mac phy cap array is null");
1553 			return QDF_STATUS_E_FAILURE;
1554 		}
1555 
1556 		mac_phy_cap = &mac_phy_cap_arr[pdev_id];
1557 		if (!mac_phy_cap) {
1558 			spectral_err("mac phy cap is null");
1559 			return QDF_STATUS_E_FAILURE;
1560 		}
1561 
1562 		table_id = mac_phy_cap->chainmask_table_id;
1563 		table =  &ext_svc_param->chainmask_table[table_id];
1564 		if (!table) {
1565 			spectral_err("chainmask table not found");
1566 			return QDF_STATUS_E_FAILURE;
1567 		}
1568 
1569 		for (j = 0; j < table->num_valid_chainmasks; j++) {
1570 			pcap->agile_spectral_cap |=
1571 				table->cap_list[j].supports_aSpectral;
1572 			pcap->agile_spectral_cap_160 |=
1573 				table->cap_list[j].supports_aSpectral_160;
1574 		}
1575 		pcap->agile_spectral_cap_80p80 = pcap->agile_spectral_cap_160;
1576 	} else {
1577 		pcap->agile_spectral_cap = false;
1578 		pcap->agile_spectral_cap_160 = false;
1579 		pcap->agile_spectral_cap_80p80 = false;
1580 	}
1581 
1582 	if (scaling_params) {
1583 		for (param_idx = 0; param_idx < num_bin_scaling_params;
1584 		     param_idx++) {
1585 			if (scaling_params[param_idx].pdev_id == pdev_id) {
1586 				pcap->is_scaling_params_populated = true;
1587 				pcap->formula_id =
1588 				    scaling_params[param_idx].formula_id;
1589 				pcap->low_level_offset =
1590 				    scaling_params[param_idx].low_level_offset;
1591 				pcap->high_level_offset =
1592 				    scaling_params[param_idx].high_level_offset;
1593 				pcap->rssi_thr =
1594 				    scaling_params[param_idx].rssi_thr;
1595 				pcap->default_agc_max_gain =
1596 				 scaling_params[param_idx].default_agc_max_gain;
1597 				break;
1598 			}
1599 		}
1600 	}
1601 
1602 	pcap->num_detectors_20mhz = 1;
1603 	pcap->num_detectors_40mhz = 1;
1604 	pcap->num_detectors_80mhz = 1;
1605 	if (target_type == TARGET_TYPE_QCN9000 ||
1606 	    target_type == TARGET_TYPE_QCA6490) {
1607 		pcap->num_detectors_160mhz = 1;
1608 		pcap->num_detectors_80p80mhz = 1;
1609 	} else {
1610 		pcap->num_detectors_160mhz = 2;
1611 		pcap->num_detectors_80p80mhz = 2;
1612 	}
1613 
1614 	return QDF_STATUS_SUCCESS;
1615 }
1616 
1617 #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION
1618 /**
1619  * target_if_init_spectral_simulation_ops() - Initialize spectral target_if
1620  * internal operations with functions related to spectral simulation
1621  * @p_sops: spectral low level ops table
1622  *
1623  * Initialize spectral target_if internal operations with functions
1624  * related to spectral simulation
1625  *
1626  * Return: None
1627  */
1628 static void
1629 target_if_init_spectral_simulation_ops(struct target_if_spectral_ops *p_sops)
1630 {
1631 	/*
1632 	 * Spectral simulation is currently intended for platform transitions
1633 	 * where underlying HW support may not be available for some time.
1634 	 * Hence, we do not currently provide a runtime switch to turn the
1635 	 * simulation on or off.
1636 	 * In case of future requirements where runtime switches are required,
1637 	 * this can be added. But it is suggested to use application layer
1638 	 * simulation as far as possible in such cases, since the main
1639 	 * use of record and replay of samples would concern higher
1640 	 * level sample processing rather than lower level delivery.
1641 	 */
1642 	p_sops->is_spectral_enabled = target_if_spectral_sops_sim_is_enabled;
1643 	p_sops->is_spectral_active = target_if_spectral_sops_sim_is_active;
1644 	p_sops->start_spectral_scan = target_if_spectral_sops_sim_start_scan;
1645 	p_sops->stop_spectral_scan = target_if_spectral_sops_sim_stop_scan;
1646 	p_sops->configure_spectral =
1647 		target_if_spectral_sops_sim_configure_params;
1648 	p_sops->get_spectral_config = target_if_spectral_sops_sim_get_params;
1649 }
1650 
1651 #else
1652 /**
1653  * target_if_init_spectral_simulation_ops() - Initialize spectral target_if
1654  * internal operations
1655  * @p_sops: spectral low level ops table
1656  *
1657  * Return: None
1658  */
1659 static void
1660 target_if_init_spectral_simulation_ops(struct target_if_spectral_ops *p_sops)
1661 {
1662 	p_sops->is_spectral_enabled = target_if_sops_is_spectral_enabled;
1663 	p_sops->is_spectral_active = target_if_sops_is_spectral_active;
1664 	p_sops->start_spectral_scan = target_if_sops_start_spectral_scan;
1665 	p_sops->stop_spectral_scan = target_if_sops_stop_spectral_scan;
1666 	p_sops->configure_spectral = target_if_spectral_sops_configure_params;
1667 	p_sops->get_spectral_config = target_if_spectral_sops_get_params;
1668 }
1669 #endif
1670 
1671 /**
1672  * target_if_init_spectral_ops_common() - Initialize Spectral target_if internal
1673  * operations common to all Spectral chipset generations
1674  *
1675  * Initializes target_if_spectral_ops common to all chipset generations
1676  *
1677  * Return: None
1678  */
1679 static void
1680 target_if_init_spectral_ops_common(void)
1681 {
1682 	struct target_if_spectral_ops *p_sops = &spectral_ops;
1683 
1684 	p_sops->get_tsf64 = target_if_spectral_get_tsf64;
1685 	p_sops->get_capability = target_if_spectral_get_capability;
1686 	p_sops->set_rxfilter = target_if_spectral_set_rxfilter;
1687 	p_sops->get_rxfilter = target_if_spectral_get_rxfilter;
1688 
1689 	target_if_init_spectral_simulation_ops(p_sops);
1690 
1691 	p_sops->get_extension_channel =
1692 	    target_if_spectral_get_extension_channel;
1693 	p_sops->get_ctl_noisefloor = target_if_spectral_get_ctl_noisefloor;
1694 	p_sops->get_ext_noisefloor = target_if_spectral_get_ext_noisefloor;
1695 	p_sops->get_ent_spectral_mask = target_if_spectral_get_ent_mask;
1696 	p_sops->get_mac_address = target_if_spectral_get_macaddr;
1697 	p_sops->get_current_channel = target_if_spectral_get_current_channel;
1698 	p_sops->reset_hw = target_if_spectral_reset_hw;
1699 	p_sops->get_chain_noise_floor =
1700 	    target_if_spectral_get_chain_noise_floor;
1701 }
1702 
1703 /**
1704  * target_if_init_spectral_ops_gen2() - Initialize Spectral target_if internal
1705  * operations specific to Spectral chipset generation 2.
1706  *
1707  * Initializes target_if_spectral_ops specific to Spectral chipset generation 2.
1708  *
1709  * Return: None
1710  */
1711 static void
1712 target_if_init_spectral_ops_gen2(void)
1713 {
1714 	struct target_if_spectral_ops *p_sops = &spectral_ops;
1715 
1716 	p_sops->spectral_process_phyerr = target_if_process_phyerr_gen2;
1717 }
1718 
1719 /**
1720  * target_if_init_spectral_ops_gen3() - Initialize Spectral target_if internal
1721  * operations specific to Spectral chipset generation 3.
1722  *
1723  * Initializes target_if_spectral_ops specific to Spectral chipset generation 3.
1724  *
1725  * Return: None
1726  */
1727 static void
1728 target_if_init_spectral_ops_gen3(void)
1729 {
1730 	struct target_if_spectral_ops *p_sops = &spectral_ops;
1731 
1732 	p_sops->process_spectral_report =
1733 			target_if_spectral_process_report_gen3;
1734 	return;
1735 }
1736 
1737 /**
1738  * target_if_init_spectral_ops() - Initialize target_if internal Spectral
1739  * operations.
1740  * @spectral: Pointer to Spectral target_if internal private data
1741  *
1742  * Initializes all function pointers in target_if_spectral_ops for
1743  * all generations
1744  *
1745  * Return: None
1746  */
1747 static void
1748 target_if_init_spectral_ops(struct target_if_spectral *spectral)
1749 {
1750 	target_if_init_spectral_ops_common();
1751 	if (spectral->spectral_gen == SPECTRAL_GEN2)
1752 		target_if_init_spectral_ops_gen2();
1753 	else if (spectral->spectral_gen == SPECTRAL_GEN3)
1754 		target_if_init_spectral_ops_gen3();
1755 	else
1756 		spectral_err("Invalid Spectral generation");
1757 }
1758 
1759 /*
1760  * Dummy Functions:
1761  * These functions are initially registered to avoid any crashes due to
1762  * invocation of spectral functions before they are registered.
1763  */
1764 
1765 static uint64_t
1766 null_get_tsf64(void *arg)
1767 {
1768 	spectral_ops_not_registered("get_tsf64");
1769 	return 0;
1770 }
1771 
1772 static uint32_t
1773 null_get_capability(void *arg, enum spectral_capability_type type)
1774 {
1775 	/*
1776 	 * TODO : We should have conditional compilation to get the capability
1777 	 *      : We have not yet attahced ATH layer here, so there is no
1778 	 *      : way to check the HAL capbalities
1779 	 */
1780 	spectral_ops_not_registered("get_capability");
1781 
1782 	/* TODO : For the time being, we are returning TRUE */
1783 	return true;
1784 }
1785 
1786 static uint32_t
1787 null_set_rxfilter(void *arg, int rxfilter)
1788 {
1789 	spectral_ops_not_registered("set_rxfilter");
1790 	return 1;
1791 }
1792 
1793 static uint32_t
1794 null_get_rxfilter(void *arg)
1795 {
1796 	spectral_ops_not_registered("get_rxfilter");
1797 	return 0;
1798 }
1799 
1800 static uint32_t
1801 null_is_spectral_active(void *arg, enum spectral_scan_mode smode)
1802 {
1803 	spectral_ops_not_registered("is_spectral_active");
1804 	return 1;
1805 }
1806 
1807 static uint32_t
1808 null_is_spectral_enabled(void *arg, enum spectral_scan_mode smode)
1809 {
1810 	spectral_ops_not_registered("is_spectral_enabled");
1811 	return 1;
1812 }
1813 
1814 static uint32_t
1815 null_start_spectral_scan(void *arg, enum spectral_scan_mode smode,
1816 			 enum spectral_cp_error_code *err)
1817 {
1818 	spectral_ops_not_registered("start_spectral_scan");
1819 	return 1;
1820 }
1821 
1822 static uint32_t
1823 null_stop_spectral_scan(void *arg, enum spectral_scan_mode smode)
1824 {
1825 	spectral_ops_not_registered("stop_spectral_scan");
1826 	return 1;
1827 }
1828 
1829 static uint32_t
1830 null_get_extension_channel(void *arg, enum spectral_scan_mode smode)
1831 {
1832 	spectral_ops_not_registered("get_extension_channel");
1833 	return 1;
1834 }
1835 
1836 static int8_t
1837 null_get_ctl_noisefloor(void *arg)
1838 {
1839 	spectral_ops_not_registered("get_ctl_noisefloor");
1840 	return 1;
1841 }
1842 
1843 static int8_t
1844 null_get_ext_noisefloor(void *arg)
1845 {
1846 	spectral_ops_not_registered("get_ext_noisefloor");
1847 	return 0;
1848 }
1849 
1850 static uint32_t
1851 null_configure_spectral(void *arg, struct spectral_config *params,
1852 			enum spectral_scan_mode smode)
1853 {
1854 	spectral_ops_not_registered("configure_spectral");
1855 	return 0;
1856 }
1857 
1858 static uint32_t
1859 null_get_spectral_config(void *arg, struct spectral_config *params,
1860 			 enum spectral_scan_mode smode)
1861 {
1862 	spectral_ops_not_registered("get_spectral_config");
1863 	return 0;
1864 }
1865 
1866 static uint32_t
1867 null_get_ent_spectral_mask(void *arg)
1868 {
1869 	spectral_ops_not_registered("get_ent_spectral_mask");
1870 	return 0;
1871 }
1872 
1873 static uint32_t
1874 null_get_mac_address(void *arg, char *addr)
1875 {
1876 	spectral_ops_not_registered("get_mac_address");
1877 	return 0;
1878 }
1879 
1880 static uint32_t
1881 null_get_current_channel(void *arg, enum spectral_scan_mode smode)
1882 {
1883 	spectral_ops_not_registered("get_current_channel");
1884 	return 0;
1885 }
1886 
1887 static uint32_t
1888 null_reset_hw(void *arg)
1889 {
1890 	spectral_ops_not_registered("get_current_channel");
1891 	return 0;
1892 }
1893 
1894 static uint32_t
1895 null_get_chain_noise_floor(void *arg, int16_t *nf_buf)
1896 {
1897 	spectral_ops_not_registered("get_chain_noise_floor");
1898 	return 0;
1899 }
1900 
1901 static int
1902 null_spectral_process_phyerr(struct target_if_spectral *spectral,
1903 			     uint8_t *data,
1904 			     uint32_t datalen,
1905 			     struct target_if_spectral_rfqual_info *p_rfqual,
1906 			     struct target_if_spectral_chan_info *p_chaninfo,
1907 			     uint64_t tsf64,
1908 			     struct target_if_spectral_acs_stats *acs_stats)
1909 {
1910 	spectral_ops_not_registered("spectral_process_phyerr");
1911 	return 0;
1912 }
1913 
1914 static int
1915 null_process_spectral_report(struct wlan_objmgr_pdev *pdev,
1916 			     void *payload)
1917 {
1918 	spectral_ops_not_registered("process_spectral_report");
1919 	return 0;
1920 }
1921 /**
1922  * target_if_spectral_init_dummy_function_table() -
1923  * Initialize target_if internal
1924  * Spectral operations to dummy functions
1925  * @ps: Pointer to Spectral target_if internal private data
1926  *
1927  * Initialize all the function pointers in target_if_spectral_ops with
1928  * dummy functions.
1929  *
1930  * Return: None
1931  */
1932 static void
1933 target_if_spectral_init_dummy_function_table(struct target_if_spectral *ps)
1934 {
1935 	struct target_if_spectral_ops *p_sops = GET_TARGET_IF_SPECTRAL_OPS(ps);
1936 
1937 	p_sops->get_tsf64 = null_get_tsf64;
1938 	p_sops->get_capability = null_get_capability;
1939 	p_sops->set_rxfilter = null_set_rxfilter;
1940 	p_sops->get_rxfilter = null_get_rxfilter;
1941 	p_sops->is_spectral_enabled = null_is_spectral_enabled;
1942 	p_sops->is_spectral_active = null_is_spectral_active;
1943 	p_sops->start_spectral_scan = null_start_spectral_scan;
1944 	p_sops->stop_spectral_scan = null_stop_spectral_scan;
1945 	p_sops->get_extension_channel = null_get_extension_channel;
1946 	p_sops->get_ctl_noisefloor = null_get_ctl_noisefloor;
1947 	p_sops->get_ext_noisefloor = null_get_ext_noisefloor;
1948 	p_sops->configure_spectral = null_configure_spectral;
1949 	p_sops->get_spectral_config = null_get_spectral_config;
1950 	p_sops->get_ent_spectral_mask = null_get_ent_spectral_mask;
1951 	p_sops->get_mac_address = null_get_mac_address;
1952 	p_sops->get_current_channel = null_get_current_channel;
1953 	p_sops->reset_hw = null_reset_hw;
1954 	p_sops->get_chain_noise_floor = null_get_chain_noise_floor;
1955 	p_sops->spectral_process_phyerr = null_spectral_process_phyerr;
1956 	p_sops->process_spectral_report = null_process_spectral_report;
1957 }
1958 
1959 /**
1960  * target_if_spectral_register_funcs() - Initialize target_if internal Spectral
1961  * operations
1962  * @spectral: Pointer to Spectral target_if internal private data
1963  * @p: Pointer to Spectral function table
1964  *
1965  * Return: None
1966  */
1967 static void
1968 target_if_spectral_register_funcs(struct target_if_spectral *spectral,
1969 				  struct target_if_spectral_ops *p)
1970 {
1971 	struct target_if_spectral_ops *p_sops =
1972 		GET_TARGET_IF_SPECTRAL_OPS(spectral);
1973 
1974 	p_sops->get_tsf64 = p->get_tsf64;
1975 	p_sops->get_capability = p->get_capability;
1976 	p_sops->set_rxfilter = p->set_rxfilter;
1977 	p_sops->get_rxfilter = p->get_rxfilter;
1978 	p_sops->is_spectral_enabled = p->is_spectral_enabled;
1979 	p_sops->is_spectral_active = p->is_spectral_active;
1980 	p_sops->start_spectral_scan = p->start_spectral_scan;
1981 	p_sops->stop_spectral_scan = p->stop_spectral_scan;
1982 	p_sops->get_extension_channel = p->get_extension_channel;
1983 	p_sops->get_ctl_noisefloor = p->get_ctl_noisefloor;
1984 	p_sops->get_ext_noisefloor = p->get_ext_noisefloor;
1985 	p_sops->configure_spectral = p->configure_spectral;
1986 	p_sops->get_spectral_config = p->get_spectral_config;
1987 	p_sops->get_ent_spectral_mask = p->get_ent_spectral_mask;
1988 	p_sops->get_mac_address = p->get_mac_address;
1989 	p_sops->get_current_channel = p->get_current_channel;
1990 	p_sops->reset_hw = p->reset_hw;
1991 	p_sops->get_chain_noise_floor = p->get_chain_noise_floor;
1992 	p_sops->spectral_process_phyerr = p->spectral_process_phyerr;
1993 	p_sops->process_spectral_report = p->process_spectral_report;
1994 }
1995 
1996 /**
1997  * target_if_spectral_clear_stats() - Clear Spectral stats
1998  * @spectral: Pointer to Spectral target_if internal private data
1999  *
2000  * Function to clear spectral stats
2001  *
2002  * Return: None
2003  */
2004 static void
2005 target_if_spectral_clear_stats(struct target_if_spectral *spectral)
2006 {
2007 	struct target_if_spectral_ops *p_sops =
2008 		GET_TARGET_IF_SPECTRAL_OPS(spectral);
2009 
2010 	qdf_mem_zero(&spectral->spectral_stats,
2011 		     sizeof(struct target_if_spectral_stats));
2012 	spectral->spectral_stats.last_reset_tstamp =
2013 	    p_sops->get_tsf64(spectral);
2014 }
2015 
2016 /**
2017  * target_if_spectral_check_hw_capability() - Check whether HW supports spectral
2018  * @spectral: Pointer to Spectral target_if internal private data
2019  *
2020  * Function to check whether hardware supports spectral
2021  *
2022  * Return: True if HW supports Spectral, false if HW does not support Spectral
2023  */
2024 static int
2025 target_if_spectral_check_hw_capability(struct target_if_spectral *spectral)
2026 {
2027 	struct target_if_spectral_ops *p_sops = NULL;
2028 	struct spectral_caps *pcap = NULL;
2029 	int is_spectral_supported = true;
2030 
2031 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
2032 	pcap = &spectral->capability;
2033 
2034 	if (p_sops->get_capability(spectral, SPECTRAL_CAP_PHYDIAG) == false) {
2035 		is_spectral_supported = false;
2036 		spectral_info("SPECTRAL : No PHYDIAG support");
2037 		return is_spectral_supported;
2038 	}
2039 	pcap->phydiag_cap = 1;
2040 
2041 	if (p_sops->get_capability(spectral, SPECTRAL_CAP_RADAR) == false) {
2042 		is_spectral_supported = false;
2043 		spectral_info("SPECTRAL : No RADAR support");
2044 		return is_spectral_supported;
2045 	}
2046 	pcap->radar_cap = 1;
2047 
2048 	if (p_sops->get_capability(spectral,
2049 				   SPECTRAL_CAP_SPECTRAL_SCAN) == false) {
2050 		is_spectral_supported = false;
2051 		spectral_info("SPECTRAL : No SPECTRAL SUPPORT");
2052 		return is_spectral_supported;
2053 	}
2054 	pcap->spectral_cap = 1;
2055 
2056 	if (p_sops->get_capability(spectral, SPECTRAL_CAP_ADVNCD_SPECTRAL_SCAN)
2057 	    == false) {
2058 		spectral_info("SPECTRAL : No ADVANCED SPECTRAL SUPPORT");
2059 	} else {
2060 		pcap->advncd_spectral_cap = 1;
2061 	}
2062 
2063 	return is_spectral_supported;
2064 }
2065 
2066 #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION
2067 /**
2068  * target_if_spectral_detach_simulation() - De-initialize Spectral
2069  * Simulation functionality
2070  * @spectral: Pointer to Spectral target_if internal private data
2071  *
2072  * Function to de-initialize Spectral Simulation functionality
2073  *
2074  * Return: None
2075  */
2076 static void
2077 target_if_spectral_detach_simulation(struct target_if_spectral *spectral)
2078 {
2079 	target_if_spectral_sim_detach(spectral);
2080 }
2081 
2082 #else
2083 static void
2084 target_if_spectral_detach_simulation(struct target_if_spectral *spectral)
2085 {
2086 }
2087 #endif
2088 
2089 /**
2090  * target_if_spectral_detach() - De-initialize target_if Spectral
2091  * @pdev: Pointer to pdev object
2092  *
2093  * Function to detach target_if spectral
2094  *
2095  * Return: None
2096  */
2097 static void
2098 target_if_spectral_detach(struct target_if_spectral *spectral)
2099 {
2100 	enum spectral_scan_mode smode = SPECTRAL_SCAN_MODE_NORMAL;
2101 	spectral_info("spectral detach");
2102 
2103 	if (spectral) {
2104 		for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++)
2105 			qdf_spinlock_destroy
2106 				(&spectral->param_info[smode].osps_lock);
2107 
2108 		target_if_spectral_detach_simulation(spectral);
2109 
2110 		qdf_spinlock_destroy(&spectral->spectral_lock);
2111 		qdf_spinlock_destroy(&spectral->noise_pwr_reports_lock);
2112 
2113 		qdf_mem_free(spectral);
2114 		spectral = NULL;
2115 	}
2116 }
2117 
2118 #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION
2119 /**
2120  * target_if_spectral_attach_simulation() - Initialize Spectral Simulation
2121  * functionality
2122  * @spectral: Pointer to Spectral target_if internal private data
2123  *
2124  * Function to initialize spectral simulation functionality
2125  *
2126  * Return: 0 on success, negative error code on failure
2127  */
2128 static int
2129 target_if_spectral_attach_simulation(struct target_if_spectral *spectral)
2130 {
2131 	if (target_if_spectral_sim_attach(spectral)) {
2132 		qdf_mem_free(spectral);
2133 		return -EPERM;
2134 	}
2135 	return 0;
2136 }
2137 
2138 #else
2139 static int
2140 target_if_spectral_attach_simulation(struct target_if_spectral *spectral)
2141 {
2142 	return 0;
2143 }
2144 #endif
2145 
2146 /**
2147  * target_if_spectral_len_adj_swar_init() - Initialize FFT bin length adjustment
2148  * related info
2149  * @swar: Pointer to Spectral FFT bin length adjustment SWAR params
2150  * @target_type: Target type
2151  *
2152  * Function to Initialize parameters related to Spectral FFT bin
2153  * length adjustment SWARs.
2154  *
2155  * Return: void
2156  */
2157 static void
2158 target_if_spectral_len_adj_swar_init(struct spectral_fft_bin_len_adj_swar *swar,
2159 				     uint32_t target_type)
2160 {
2161 	if (target_type == TARGET_TYPE_QCA8074V2 ||
2162 	    target_type == TARGET_TYPE_QCN9000 ||
2163 	    target_type == TARGET_TYPE_QCA5018 ||
2164 	    target_type == TARGET_TYPE_QCA6750 ||
2165 	    target_type == TARGET_TYPE_QCA6490)
2166 		swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE;
2167 	else if (target_type == TARGET_TYPE_QCA8074 ||
2168 		 target_type == TARGET_TYPE_QCA6018 ||
2169 		 target_type == TARGET_TYPE_QCA6390)
2170 		swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE;
2171 	else
2172 		swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_NO_WAR;
2173 
2174 	if (target_type == TARGET_TYPE_QCA8074 ||
2175 	    target_type == TARGET_TYPE_QCA8074V2 ||
2176 	    target_type == TARGET_TYPE_QCA6018 ||
2177 	    target_type == TARGET_TYPE_QCA5018 ||
2178 	    target_type == TARGET_TYPE_QCN9000 ||
2179 	    target_type == TARGET_TYPE_QCA6490) {
2180 		swar->inband_fftbin_size_adj = 1;
2181 		swar->null_fftbin_adj = 1;
2182 	} else {
2183 		swar->inband_fftbin_size_adj = 0;
2184 		swar->null_fftbin_adj = 0;
2185 	}
2186 
2187 	if (target_type == TARGET_TYPE_QCA8074V2)
2188 		swar->packmode_fftbin_size_adj = 1;
2189 	else
2190 		swar->packmode_fftbin_size_adj = 0;
2191 }
2192 
2193 /**
2194  * target_if_spectral_report_params_init() - Initialize parameters which
2195  * describes the structure of Spectral reports
2196  *
2197  * @rparams: Pointer to Spectral report parameter object
2198  * @target_type: target type
2199  *
2200  * Function to Initialize parameters related to the structure of Spectral
2201  * reports.
2202  *
2203  * Return: void
2204  */
2205 static void
2206 target_if_spectral_report_params_init(
2207 			struct spectral_report_params *rparams,
2208 			uint32_t target_type)
2209 {
2210 	enum spectral_scan_mode smode;
2211 
2212 	/* This entries are currently used by gen3 chipsets only. Hence
2213 	 * initialization is done for gen3 alone. In future if other generations
2214 	 * needs to use them they have to add proper initial values.
2215 	 */
2216 	if (target_type == TARGET_TYPE_QCN9000 ||
2217 	    target_type == TARGET_TYPE_QCA5018 ||
2218 	    target_type == TARGET_TYPE_QCA6750 ||
2219 	    target_type == TARGET_TYPE_QCA6490) {
2220 		rparams->version = SPECTRAL_REPORT_FORMAT_VERSION_2;
2221 		rparams->num_spectral_detectors =
2222 				NUM_SPECTRAL_DETECTORS_GEN3_V2;
2223 		smode = SPECTRAL_SCAN_MODE_NORMAL;
2224 		for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++)
2225 			rparams->fragmentation_160[smode] = false;
2226 		rparams->max_agile_ch_width = CH_WIDTH_80P80MHZ;
2227 	} else {
2228 		rparams->version = SPECTRAL_REPORT_FORMAT_VERSION_1;
2229 		rparams->num_spectral_detectors =
2230 				NUM_SPECTRAL_DETECTORS_GEN3_V1;
2231 		smode = SPECTRAL_SCAN_MODE_NORMAL;
2232 		for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++)
2233 			rparams->fragmentation_160[smode] = true;
2234 		rparams->max_agile_ch_width = CH_WIDTH_80MHZ;
2235 	}
2236 
2237 	switch (rparams->version) {
2238 	case SPECTRAL_REPORT_FORMAT_VERSION_1:
2239 		rparams->ssumaary_padding_bytes =
2240 			NUM_PADDING_BYTES_SSCAN_SUMARY_REPORT_GEN3_V1;
2241 		rparams->fft_report_hdr_len =
2242 			FFT_REPORT_HEADER_LENGTH_GEN3_V1;
2243 		break;
2244 	case SPECTRAL_REPORT_FORMAT_VERSION_2:
2245 		rparams->ssumaary_padding_bytes =
2246 			NUM_PADDING_BYTES_SSCAN_SUMARY_REPORT_GEN3_V2;
2247 		rparams->fft_report_hdr_len =
2248 			FFT_REPORT_HEADER_LENGTH_GEN3_V2;
2249 		break;
2250 	default:
2251 		qdf_assert_always(0);
2252 	}
2253 
2254 	rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_0] =
2255 						SPECTRAL_SCAN_MODE_NORMAL;
2256 	if (target_type == TARGET_TYPE_QCN9000 ||
2257 	    target_type == TARGET_TYPE_QCA6490) {
2258 		rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_1] =
2259 						SPECTRAL_SCAN_MODE_AGILE;
2260 		rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_2] =
2261 						SPECTRAL_SCAN_MODE_INVALID;
2262 	} else {
2263 		rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_1] =
2264 						SPECTRAL_SCAN_MODE_NORMAL;
2265 		rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_2] =
2266 						SPECTRAL_SCAN_MODE_AGILE;
2267 	}
2268 }
2269 
2270 /**
2271  * target_if_spectral_timestamp_war_init() - Initialize Spectral timestamp WAR
2272  * related info
2273  * @twar: Pointer to Spectral timstamp WAR related info
2274  *
2275  * Function to Initialize parameters related to Spectral timestamp WAR
2276  *
2277  * Return: void
2278  */
2279 static void
2280 target_if_spectral_timestamp_war_init(struct spectral_timestamp_war *twar)
2281 {
2282 	enum spectral_scan_mode smode;
2283 
2284 	smode = SPECTRAL_SCAN_MODE_NORMAL;
2285 	for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) {
2286 		twar->last_fft_timestamp[smode] = 0;
2287 		twar->timestamp_war_offset[smode] = 0;
2288 	}
2289 	twar->target_reset_count = 0;
2290 }
2291 
2292 /**
2293  * target_if_pdev_spectral_init() - Initialize target_if Spectral
2294  * functionality for the given pdev
2295  * @pdev: Pointer to pdev object
2296  *
2297  * Function to initialize pointer to spectral target_if internal private data
2298  *
2299  * Return: On success, pointer to Spectral target_if internal private data, on
2300  * failure, NULL
2301  */
2302 void *
2303 target_if_pdev_spectral_init(struct wlan_objmgr_pdev *pdev)
2304 {
2305 	struct target_if_spectral_ops *p_sops = NULL;
2306 	struct target_if_spectral *spectral = NULL;
2307 	uint32_t target_type;
2308 	uint32_t target_revision;
2309 	struct wlan_objmgr_psoc *psoc;
2310 	struct wlan_lmac_if_target_tx_ops *tgt_tx_ops;
2311 	enum spectral_scan_mode smode = SPECTRAL_SCAN_MODE_NORMAL;
2312 	QDF_STATUS status;
2313 	struct wlan_lmac_if_tx_ops *tx_ops;
2314 
2315 	if (!pdev) {
2316 		spectral_err("SPECTRAL: pdev is NULL!");
2317 		return NULL;
2318 	}
2319 	spectral = (struct target_if_spectral *)qdf_mem_malloc(
2320 			sizeof(struct target_if_spectral));
2321 	if (!spectral)
2322 		return spectral;
2323 
2324 	qdf_mem_zero(spectral, sizeof(struct target_if_spectral));
2325 	/* Store pdev in Spectral */
2326 	spectral->pdev_obj = pdev;
2327 	spectral->vdev_id[SPECTRAL_SCAN_MODE_NORMAL] = WLAN_INVALID_VDEV_ID;
2328 	spectral->vdev_id[SPECTRAL_SCAN_MODE_AGILE] = WLAN_INVALID_VDEV_ID;
2329 
2330 	psoc = wlan_pdev_get_psoc(pdev);
2331 
2332 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
2333 	if (!tx_ops) {
2334 		spectral_err("tx_ops is NULL");
2335 		qdf_mem_free(spectral);
2336 		return NULL;
2337 	}
2338 
2339 	tgt_tx_ops = &tx_ops->target_tx_ops;
2340 
2341 	if (tgt_tx_ops->tgt_get_tgt_type) {
2342 		target_type = tgt_tx_ops->tgt_get_tgt_type(psoc);
2343 	} else {
2344 		qdf_mem_free(spectral);
2345 		return NULL;
2346 	}
2347 
2348 	if (tgt_tx_ops->tgt_get_tgt_revision) {
2349 		target_revision = tgt_tx_ops->tgt_get_tgt_revision(psoc);
2350 	} else {
2351 		qdf_mem_free(spectral);
2352 		return NULL;
2353 	}
2354 
2355 	/* init the function ptr table */
2356 	target_if_spectral_init_dummy_function_table(spectral);
2357 
2358 	/* get spectral function table */
2359 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
2360 	/* TODO : Should this be called here of after ath_attach ? */
2361 	if (p_sops->get_capability(spectral, SPECTRAL_CAP_PHYDIAG))
2362 		spectral_info("HAL_CAP_PHYDIAG : Capable");
2363 
2364 	/* TODO: Need to fix the capablity check for RADAR */
2365 	if (p_sops->get_capability(spectral, SPECTRAL_CAP_RADAR))
2366 		spectral_info("HAL_CAP_RADAR   : Capable");
2367 
2368 	/* TODO : Need to fix the capablity check for SPECTRAL */
2369 	/* TODO : Should this be called here of after ath_attach ? */
2370 	if (p_sops->get_capability(spectral, SPECTRAL_CAP_SPECTRAL_SCAN))
2371 		spectral_info("HAL_CAP_SPECTRAL_SCAN : Capable");
2372 
2373 	qdf_spinlock_create(&spectral->spectral_lock);
2374 	qdf_spinlock_create(&spectral->noise_pwr_reports_lock);
2375 	target_if_spectral_clear_stats(spectral);
2376 
2377 	if (target_type == TARGET_TYPE_QCA8074 ||
2378 	    target_type == TARGET_TYPE_QCA8074V2 ||
2379 	    target_type == TARGET_TYPE_QCA6018 ||
2380 	    target_type == TARGET_TYPE_QCA5018 ||
2381 	    target_type == TARGET_TYPE_QCA6390 ||
2382 	    target_type == TARGET_TYPE_QCA6490 ||
2383 	    target_type == TARGET_TYPE_QCN9000 ||
2384 	    target_type == TARGET_TYPE_QCA6750)
2385 		spectral->direct_dma_support = true;
2386 
2387 	target_if_spectral_len_adj_swar_init(&spectral->len_adj_swar,
2388 					     target_type);
2389 	target_if_spectral_report_params_init(&spectral->rparams, target_type);
2390 
2391 	if ((target_type == TARGET_TYPE_QCA8074) ||
2392 	    (target_type == TARGET_TYPE_QCA8074V2) ||
2393 	    (target_type == TARGET_TYPE_QCA6018) ||
2394 	    (target_type == TARGET_TYPE_QCA5018) ||
2395 	    (target_type == TARGET_TYPE_QCN9000) ||
2396 	    (target_type == TARGET_TYPE_QCA6290) ||
2397 	    (target_type == TARGET_TYPE_QCA6390) ||
2398 	    (target_type == TARGET_TYPE_QCA6490) ||
2399 	    (target_type == TARGET_TYPE_QCA6750)) {
2400 		spectral->spectral_gen = SPECTRAL_GEN3;
2401 		spectral->hdr_sig_exp = SPECTRAL_PHYERR_SIGNATURE_GEN3;
2402 		spectral->tag_sscan_summary_exp =
2403 		    TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN3;
2404 		spectral->tag_sscan_fft_exp = TLV_TAG_SEARCH_FFT_REPORT_GEN3;
2405 		spectral->tlvhdr_size = SPECTRAL_PHYERR_TLVSIZE_GEN3;
2406 	} else {
2407 		spectral->spectral_gen = SPECTRAL_GEN2;
2408 		spectral->hdr_sig_exp = SPECTRAL_PHYERR_SIGNATURE_GEN2;
2409 		spectral->tag_sscan_summary_exp =
2410 		    TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN2;
2411 		spectral->tag_sscan_fft_exp = TLV_TAG_SEARCH_FFT_REPORT_GEN2;
2412 		spectral->tlvhdr_size = sizeof(struct spectral_phyerr_tlv_gen2);
2413 	}
2414 
2415 	status = target_if_init_spectral_param_min_max(
2416 					&spectral->param_min_max,
2417 					spectral->spectral_gen, target_type);
2418 	if (QDF_IS_STATUS_ERROR(status)) {
2419 		spectral_err("Failed to initialize parameter min max values");
2420 		goto fail;
2421 	}
2422 
2423 	target_if_init_spectral_param_properties(spectral);
2424 	/* Init spectral capability */
2425 	if (target_if_init_spectral_capability(spectral, target_type) !=
2426 					QDF_STATUS_SUCCESS) {
2427 		qdf_mem_free(spectral);
2428 		return NULL;
2429 	}
2430 	if (target_if_spectral_attach_simulation(spectral) < 0)
2431 		return NULL;
2432 
2433 	target_if_init_spectral_ops(spectral);
2434 	target_if_spectral_timestamp_war_init(&spectral->timestamp_war);
2435 
2436 	/* Spectral mode specific init */
2437 	for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) {
2438 		spectral->params_valid[smode] = false;
2439 		qdf_spinlock_create(&spectral->param_info[smode].osps_lock);
2440 		spectral->param_info[smode].osps_cache.osc_is_valid = 0;
2441 	}
2442 
2443 	target_if_spectral_register_funcs(spectral, &spectral_ops);
2444 
2445 	if (target_if_spectral_check_hw_capability(spectral) == false) {
2446 		goto fail;
2447 	} else {
2448 		/*
2449 		 * TODO: Once the driver architecture transitions to chipset
2450 		 * versioning based checks, reflect this here.
2451 		 */
2452 		spectral->is_160_format = false;
2453 		spectral->is_lb_edge_extrabins_format = false;
2454 		spectral->is_rb_edge_extrabins_format = false;
2455 
2456 		if (target_type == TARGET_TYPE_QCA9984 ||
2457 		    target_type == TARGET_TYPE_QCA9888) {
2458 			spectral->is_160_format = true;
2459 			spectral->is_lb_edge_extrabins_format = true;
2460 			spectral->is_rb_edge_extrabins_format = true;
2461 		} else  if ((target_type == TARGET_TYPE_AR900B) &&
2462 			    (target_revision == AR900B_REV_2)) {
2463 			spectral->is_rb_edge_extrabins_format = true;
2464 		}
2465 
2466 		if (target_type == TARGET_TYPE_QCA9984 ||
2467 		    target_type == TARGET_TYPE_QCA9888)
2468 			spectral->is_sec80_rssi_war_required = true;
2469 
2470 		spectral->use_nl_bcast = SPECTRAL_USE_NL_BCAST;
2471 
2472 		if (spectral->spectral_gen == SPECTRAL_GEN3)
2473 			init_160mhz_delivery_state_machine(spectral);
2474 	}
2475 
2476 	return spectral;
2477 
2478 fail:
2479 	target_if_spectral_detach(spectral);
2480 	return NULL;
2481 }
2482 
2483 /**
2484  * target_if_pdev_spectral_deinit() - De-initialize target_if Spectral
2485  * functionality for the given pdev
2486  * @pdev: Pointer to pdev object
2487  *
2488  * Function to de-initialize pointer to spectral target_if internal private data
2489  *
2490  * Return: None
2491  */
2492 void
2493 target_if_pdev_spectral_deinit(struct wlan_objmgr_pdev *pdev)
2494 {
2495 	struct target_if_spectral *spectral = NULL;
2496 
2497 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2498 	if (!spectral) {
2499 		spectral_err("SPECTRAL : Module doesn't exist");
2500 		return;
2501 	}
2502 	target_if_spectral_detach(spectral);
2503 
2504 	return;
2505 }
2506 
2507 /**
2508  * target_if_psoc_spectral_deinit() - De-initialize target_if Spectral
2509  * functionality for the given psoc
2510  * @psoc: Pointer to psoc object
2511  *
2512  * Function to de-initialize pointer to psoc spectral target_if internal
2513  * private data
2514  *
2515  * Return: None
2516  */
2517 static void
2518 target_if_psoc_spectral_deinit(struct wlan_objmgr_psoc *psoc)
2519 {
2520 	struct target_if_psoc_spectral *psoc_spectral;
2521 
2522 	if (!psoc) {
2523 		spectral_err("psoc is null");
2524 		return;
2525 	}
2526 
2527 	psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
2528 	if (!psoc_spectral) {
2529 		spectral_err("Spectral target_if psoc object is null");
2530 		return;
2531 	}
2532 
2533 	qdf_mem_free(psoc_spectral);
2534 }
2535 
2536 /**
2537  * target_if_psoc_spectral_init() - Initialize target_if Spectral
2538  * functionality for the given psoc
2539  * @psoc: Pointer to psoc object
2540  *
2541  * Function to initialize pointer to psoc spectral target_if internal
2542  * private data
2543  *
2544  * Return: On success, pointer to Spectral psoc target_if internal
2545  * private data, on failure, NULL
2546  */
2547 static void *
2548 target_if_psoc_spectral_init(struct wlan_objmgr_psoc *psoc)
2549 {
2550 	struct target_if_psoc_spectral *psoc_spectral = NULL;
2551 
2552 	if (!psoc) {
2553 		spectral_err("psoc is null");
2554 		goto fail;
2555 	}
2556 
2557 	psoc_spectral = (struct target_if_psoc_spectral *)qdf_mem_malloc(
2558 			sizeof(struct target_if_psoc_spectral));
2559 	if (!psoc_spectral) {
2560 		spectral_err("Spectral lmac psoc object allocation failed");
2561 		goto fail;
2562 	}
2563 
2564 	psoc_spectral->psoc_obj = psoc;
2565 
2566 	return psoc_spectral;
2567 
2568 fail:
2569 	if (psoc_spectral)
2570 		target_if_psoc_spectral_deinit(psoc);
2571 
2572 	return psoc_spectral;
2573 }
2574 
2575 /* target_if_spectral_find_agile_width() - Given a channel width enum, find the
2576  * corresponding translation for Agile channel width.
2577  * @spectral: pointer to Spectral object
2578  * @chwidth: operating channel width
2579  * @is_80_80_agile: Indicates an 80+80 agile Scan request
2580  *
2581  * Return: The translated channel width enum.
2582  */
2583 static enum phy_ch_width
2584 target_if_spectral_find_agile_width(struct target_if_spectral *spectral,
2585 				    enum phy_ch_width chwidth,
2586 				    bool is_80_80_agile)
2587 {
2588 	enum phy_ch_width agile_width;
2589 	struct wlan_objmgr_pdev *pdev;
2590 	struct wlan_objmgr_psoc *psoc;
2591 
2592 	if (!spectral) {
2593 		spectral_err("Spectral object is null");
2594 		return CH_WIDTH_INVALID;
2595 	}
2596 
2597 	pdev =  spectral->pdev_obj;
2598 	if (!pdev) {
2599 		spectral_err("pdev is null");
2600 		return CH_WIDTH_INVALID;
2601 	}
2602 
2603 	psoc = wlan_pdev_get_psoc(pdev);
2604 	if (!psoc) {
2605 		spectral_err("psoc is null");
2606 		return CH_WIDTH_INVALID;
2607 	}
2608 
2609 	switch (chwidth) {
2610 	case CH_WIDTH_20MHZ:
2611 		agile_width = CH_WIDTH_20MHZ;
2612 		break;
2613 
2614 	case CH_WIDTH_40MHZ:
2615 		agile_width = CH_WIDTH_40MHZ;
2616 		break;
2617 
2618 	case CH_WIDTH_80MHZ:
2619 		agile_width = CH_WIDTH_80MHZ;
2620 		break;
2621 
2622 	case CH_WIDTH_80P80MHZ:
2623 		if (wlan_psoc_nif_fw_ext_cap_get(psoc,
2624 		    WLAN_SOC_RESTRICTED_80P80_SUPPORT) && !is_80_80_agile)
2625 			agile_width = CH_WIDTH_160MHZ;
2626 		else
2627 			agile_width = CH_WIDTH_80P80MHZ;
2628 
2629 		if (agile_width > spectral->rparams.max_agile_ch_width)
2630 			agile_width = spectral->rparams.max_agile_ch_width;
2631 		break;
2632 
2633 	case CH_WIDTH_160MHZ:
2634 		if (wlan_psoc_nif_fw_ext_cap_get(psoc,
2635 		    WLAN_SOC_RESTRICTED_80P80_SUPPORT) && is_80_80_agile)
2636 			agile_width = CH_WIDTH_80P80MHZ;
2637 		else
2638 			agile_width = CH_WIDTH_160MHZ;
2639 
2640 		if (agile_width > spectral->rparams.max_agile_ch_width)
2641 			agile_width = spectral->rparams.max_agile_ch_width;
2642 		break;
2643 
2644 	default:
2645 		spectral_err("Invalid channel width %d", chwidth);
2646 		agile_width = CH_WIDTH_INVALID;
2647 		break;
2648 	}
2649 
2650 	return agile_width;
2651 }
2652 
2653 /**
2654  * target_if_calculate_center_freq() - Helper routine to
2655  * check whether given frequency is center frequency of a
2656  * WLAN channel
2657  *
2658  * @spectral: Pointer to Spectral object
2659  * @chan_freq: Center frequency of a WLAN channel
2660  * @is_valid: Indicates whether given frequency is valid
2661  *
2662  * Return: QDF_STATUS
2663  */
2664 static QDF_STATUS
2665 target_if_is_center_freq_of_any_chan(struct wlan_objmgr_pdev *pdev,
2666 				     uint32_t chan_freq,
2667 				     bool *is_valid)
2668 {
2669 	struct regulatory_channel *cur_chan_list;
2670 	int i;
2671 
2672 	if (!pdev) {
2673 		spectral_err("pdev object is null");
2674 		return QDF_STATUS_E_FAILURE;
2675 	}
2676 
2677 	if (!is_valid) {
2678 		spectral_err("is valid argument is null");
2679 		return QDF_STATUS_E_FAILURE;
2680 	}
2681 
2682 	cur_chan_list = qdf_mem_malloc(NUM_CHANNELS * sizeof(*cur_chan_list));
2683 	if (!cur_chan_list)
2684 		return QDF_STATUS_E_FAILURE;
2685 
2686 	if (wlan_reg_get_current_chan_list(
2687 			pdev, cur_chan_list) != QDF_STATUS_SUCCESS) {
2688 		spectral_err("Failed to get cur_chan list");
2689 		qdf_mem_free(cur_chan_list);
2690 		return QDF_STATUS_E_FAILURE;
2691 	}
2692 
2693 	*is_valid = false;
2694 	for (i = 0; i < NUM_CHANNELS; i++) {
2695 		uint32_t flags;
2696 		uint32_t center_freq;
2697 
2698 		flags = cur_chan_list[i].chan_flags;
2699 		center_freq = cur_chan_list[i].center_freq;
2700 
2701 		if (!(flags & REGULATORY_CHAN_DISABLED) &&
2702 		    (center_freq == chan_freq)) {
2703 			*is_valid = true;
2704 			break;
2705 		}
2706 	}
2707 
2708 	qdf_mem_free(cur_chan_list);
2709 
2710 	return QDF_STATUS_SUCCESS;
2711 }
2712 
2713 /**
2714  * target_if_calculate_center_freq() - Helper routine to
2715  * find the center frequency of the agile span from a
2716  * WLAN channel center frequency
2717  *
2718  * @spectral: Pointer to Spectral object
2719  * @ch_width: Channel width array
2720  * @chan_freq: Center frequency of a WLAN channel
2721  * @center_freq: Pointer to center frequency
2722  *
2723  * Return: QDF_STATUS
2724  */
2725 static QDF_STATUS
2726 target_if_calculate_center_freq(struct target_if_spectral *spectral,
2727 				enum phy_ch_width *ch_width,
2728 				uint16_t chan_freq,
2729 				uint16_t *center_freq)
2730 {
2731 	enum phy_ch_width agile_ch_width;
2732 
2733 	if (!spectral) {
2734 		spectral_err("spectral target if object is null");
2735 		return QDF_STATUS_E_FAILURE;
2736 	}
2737 
2738 	if (!ch_width) {
2739 		spectral_err("Channel width array is null");
2740 		return QDF_STATUS_E_INVAL;
2741 	}
2742 	agile_ch_width = ch_width[SPECTRAL_SCAN_MODE_AGILE];
2743 
2744 	if (!center_freq) {
2745 		spectral_err("center_freq argument is null");
2746 		return QDF_STATUS_E_FAILURE;
2747 	}
2748 
2749 	if (agile_ch_width == CH_WIDTH_20MHZ) {
2750 		*center_freq = chan_freq;
2751 	} else {
2752 		uint16_t start_freq;
2753 		uint16_t end_freq;
2754 		const struct bonded_channel_freq *bonded_chan_ptr = NULL;
2755 		enum channel_state state;
2756 
2757 		state = wlan_reg_get_5g_bonded_channel_and_state_for_freq
2758 			(spectral->pdev_obj, chan_freq, agile_ch_width,
2759 			 &bonded_chan_ptr);
2760 		if (state == CHANNEL_STATE_DISABLE ||
2761 		    state == CHANNEL_STATE_INVALID) {
2762 			spectral_err("Channel state is disable or invalid");
2763 			return QDF_STATUS_E_FAILURE;
2764 		}
2765 		if (!bonded_chan_ptr) {
2766 			spectral_err("Bonded channel is not found");
2767 			return QDF_STATUS_E_FAILURE;
2768 		}
2769 		start_freq = bonded_chan_ptr->start_freq;
2770 		end_freq = bonded_chan_ptr->end_freq;
2771 		*center_freq = (start_freq + end_freq) >> 1;
2772 	}
2773 
2774 	return QDF_STATUS_SUCCESS;
2775 }
2776 
2777 /**
2778  * target_if_validate_center_freq() - Helper routine to
2779  * validate user provided agile center frequency
2780  *
2781  * @spectral: Pointer to Spectral object
2782  * @ch_width: Channel width array
2783  * @center_freq: User provided agile span center frequency
2784  * @is_valid: Indicates whether agile span center frequency is valid
2785  *
2786  * Return: QDF_STATUS
2787  */
2788 static QDF_STATUS
2789 target_if_validate_center_freq(struct target_if_spectral *spectral,
2790 			       enum phy_ch_width *ch_width,
2791 			       uint16_t center_freq,
2792 			       bool *is_valid)
2793 {
2794 	enum phy_ch_width agile_ch_width;
2795 	struct wlan_objmgr_pdev *pdev;
2796 	QDF_STATUS status;
2797 
2798 	if (!spectral) {
2799 		spectral_err("spectral target if object is null");
2800 		return QDF_STATUS_E_FAILURE;
2801 	}
2802 
2803 	if (!ch_width) {
2804 		spectral_err("channel width array is null");
2805 		return QDF_STATUS_E_INVAL;
2806 	}
2807 	agile_ch_width = ch_width[SPECTRAL_SCAN_MODE_AGILE];
2808 
2809 	if (!is_valid) {
2810 		spectral_err("is_valid argument is null");
2811 		return QDF_STATUS_E_FAILURE;
2812 	}
2813 
2814 	pdev = spectral->pdev_obj;
2815 
2816 	if (agile_ch_width == CH_WIDTH_20MHZ) {
2817 		status = target_if_is_center_freq_of_any_chan
2818 				(pdev, center_freq, is_valid);
2819 		if (QDF_IS_STATUS_ERROR(status))
2820 			return QDF_STATUS_E_FAILURE;
2821 	} else {
2822 		uint16_t start_freq;
2823 		uint16_t end_freq;
2824 		const struct bonded_channel_freq *bonded_chan_ptr = NULL;
2825 		bool is_chan;
2826 
2827 		status = target_if_is_center_freq_of_any_chan
2828 				(pdev, center_freq + FREQ_OFFSET_10MHZ,
2829 				 &is_chan);
2830 		if (QDF_IS_STATUS_ERROR(status))
2831 			return QDF_STATUS_E_FAILURE;
2832 
2833 		if (is_chan) {
2834 			uint32_t calulated_center_freq;
2835 			enum channel_state st;
2836 
2837 			st = wlan_reg_get_5g_bonded_channel_and_state_for_freq
2838 				(pdev, center_freq + FREQ_OFFSET_10MHZ,
2839 				 agile_ch_width,
2840 				 &bonded_chan_ptr);
2841 			if (st == CHANNEL_STATE_DISABLE ||
2842 			    st == CHANNEL_STATE_INVALID) {
2843 				spectral_err("Channel state disable/invalid");
2844 				return QDF_STATUS_E_FAILURE;
2845 			}
2846 			if (!bonded_chan_ptr) {
2847 				spectral_err("Bonded channel is not found");
2848 				return QDF_STATUS_E_FAILURE;
2849 			}
2850 			start_freq = bonded_chan_ptr->start_freq;
2851 			end_freq = bonded_chan_ptr->end_freq;
2852 			calulated_center_freq = (start_freq + end_freq) >> 1;
2853 			*is_valid = (center_freq == calulated_center_freq);
2854 		} else {
2855 			*is_valid = false;
2856 		}
2857 	}
2858 
2859 	return QDF_STATUS_SUCCESS;
2860 }
2861 
2862 /**
2863  * target_if_is_agile_span_overlap_with_operating_span() - Helper routine to
2864  * check whether agile span overlaps with current operating band.
2865  *
2866  * @spectral: Pointer to Spectral object
2867  * @ch_width: Channel width array
2868  * @center_freq: Agile span center frequency
2869  * @is_overlapping: Indicates whether Agile span overlaps with operating span
2870  *
2871  * Helper routine to check whether agile span overlaps with current
2872  * operating band.
2873  *
2874  * Return: QDF_STATUS
2875  */
2876 static QDF_STATUS
2877 target_if_is_agile_span_overlap_with_operating_span
2878 			(struct target_if_spectral *spectral,
2879 			 enum phy_ch_width *ch_width,
2880 			 struct spectral_config_frequency *center_freq,
2881 			 bool *is_overlapping)
2882 {
2883 	enum phy_ch_width op_ch_width;
2884 	enum phy_ch_width agile_ch_width;
2885 	const struct bonded_channel_freq *bonded_chan_ptr = NULL;
2886 	struct wlan_objmgr_vdev *vdev;
2887 	struct wlan_objmgr_pdev *pdev;
2888 	int16_t chan_freq;
2889 	uint32_t op_start_freq;
2890 	uint32_t op_end_freq;
2891 	uint32_t agile_start_freq;
2892 	uint32_t agile_end_freq;
2893 	uint32_t cfreq2;
2894 
2895 	if (!spectral) {
2896 		spectral_err("Spectral object is NULL");
2897 		return QDF_STATUS_E_FAILURE;
2898 	}
2899 
2900 	pdev  = spectral->pdev_obj;
2901 	if (!pdev) {
2902 		spectral_err("pdev object is NULL");
2903 		return QDF_STATUS_E_FAILURE;
2904 	}
2905 
2906 	if (!ch_width) {
2907 		spectral_err("channel width array is null");
2908 		return QDF_STATUS_E_FAILURE;
2909 	}
2910 	op_ch_width = ch_width[SPECTRAL_SCAN_MODE_NORMAL];
2911 	if (op_ch_width == CH_WIDTH_INVALID) {
2912 		spectral_err("Invalid channel width");
2913 		return QDF_STATUS_E_INVAL;
2914 	}
2915 	agile_ch_width = ch_width[SPECTRAL_SCAN_MODE_AGILE];
2916 	if (agile_ch_width == CH_WIDTH_INVALID) {
2917 		spectral_err("Invalid channel width");
2918 		return QDF_STATUS_E_INVAL;
2919 	}
2920 
2921 	if (!is_overlapping) {
2922 		spectral_err("Argument(is_overlapping) is NULL");
2923 		return QDF_STATUS_E_FAILURE;
2924 	}
2925 	*is_overlapping = false;
2926 
2927 	vdev = target_if_spectral_get_vdev(spectral, SPECTRAL_SCAN_MODE_AGILE);
2928 	if (!vdev) {
2929 		spectral_err("vdev is NULL");
2930 		return QDF_STATUS_E_FAILURE;
2931 	}
2932 	chan_freq = target_if_vdev_get_chan_freq(vdev);
2933 	cfreq2 = target_if_vdev_get_chan_freq_seg2(vdev);
2934 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
2935 	if (cfreq2 < 0) {
2936 		spectral_err("cfreq2 is invalid");
2937 		return QDF_STATUS_E_FAILURE;
2938 	}
2939 
2940 	if (op_ch_width == CH_WIDTH_20MHZ) {
2941 		op_start_freq = chan_freq - FREQ_OFFSET_10MHZ;
2942 		op_end_freq = chan_freq + FREQ_OFFSET_10MHZ;
2943 	} else {
2944 		enum channel_state state;
2945 
2946 		state = wlan_reg_get_5g_bonded_channel_and_state_for_freq
2947 			(pdev, chan_freq, op_ch_width, &bonded_chan_ptr);
2948 		if (state == CHANNEL_STATE_DISABLE ||
2949 		    state == CHANNEL_STATE_INVALID) {
2950 			spectral_err("Channel state is disable or invalid");
2951 			return QDF_STATUS_E_FAILURE;
2952 		}
2953 		if (!bonded_chan_ptr) {
2954 			spectral_err("Bonded channel is not found");
2955 			return QDF_STATUS_E_FAILURE;
2956 		}
2957 		op_start_freq = bonded_chan_ptr->start_freq - FREQ_OFFSET_10MHZ;
2958 		op_end_freq = bonded_chan_ptr->end_freq - FREQ_OFFSET_10MHZ;
2959 	}
2960 
2961 	if (agile_ch_width == CH_WIDTH_80P80MHZ) {
2962 		agile_start_freq = center_freq->cfreq1 - FREQ_OFFSET_40MHZ;
2963 		agile_end_freq = center_freq->cfreq1 + FREQ_OFFSET_40MHZ;
2964 		if (agile_end_freq > op_start_freq &&
2965 		    op_end_freq > agile_start_freq)
2966 			*is_overlapping = true;
2967 
2968 		agile_start_freq = center_freq->cfreq2 - FREQ_OFFSET_40MHZ;
2969 		agile_end_freq = center_freq->cfreq2 + FREQ_OFFSET_40MHZ;
2970 		if (agile_end_freq > op_start_freq &&
2971 		    op_end_freq > agile_start_freq)
2972 			*is_overlapping = true;
2973 	} else {
2974 		agile_start_freq = center_freq->cfreq1 -
2975 				(wlan_reg_get_bw_value(agile_ch_width) >> 1);
2976 		agile_end_freq = center_freq->cfreq1 +
2977 				(wlan_reg_get_bw_value(agile_ch_width) >> 1);
2978 		if (agile_end_freq > op_start_freq &&
2979 		    op_end_freq > agile_start_freq)
2980 			*is_overlapping = true;
2981 	}
2982 
2983 	if (op_ch_width == CH_WIDTH_80P80MHZ) {
2984 		uint32_t sec80_start_feq;
2985 		uint32_t sec80_end_freq;
2986 
2987 		sec80_start_feq = cfreq2 - FREQ_OFFSET_40MHZ;
2988 		sec80_end_freq = cfreq2 + FREQ_OFFSET_40MHZ;
2989 
2990 		if (agile_ch_width == CH_WIDTH_80P80MHZ) {
2991 			agile_start_freq =
2992 					center_freq->cfreq1 - FREQ_OFFSET_40MHZ;
2993 			agile_end_freq =
2994 					center_freq->cfreq1 + FREQ_OFFSET_40MHZ;
2995 			if (agile_end_freq > sec80_start_feq &&
2996 			    sec80_end_freq > agile_start_freq)
2997 				*is_overlapping = true;
2998 
2999 			agile_start_freq =
3000 					center_freq->cfreq2 - FREQ_OFFSET_40MHZ;
3001 			agile_end_freq =
3002 					center_freq->cfreq2 + FREQ_OFFSET_40MHZ;
3003 			if (agile_end_freq > sec80_start_feq &&
3004 			    sec80_end_freq > agile_start_freq)
3005 				*is_overlapping = true;
3006 		} else {
3007 			agile_start_freq = center_freq->cfreq1 -
3008 				(wlan_reg_get_bw_value(agile_ch_width) >> 1);
3009 			agile_end_freq = center_freq->cfreq1 +
3010 				(wlan_reg_get_bw_value(agile_ch_width) >> 1);
3011 			if (agile_end_freq > sec80_start_feq &&
3012 			    sec80_end_freq > agile_start_freq)
3013 				*is_overlapping = true;
3014 		}
3015 	}
3016 
3017 	return QDF_STATUS_SUCCESS;
3018 }
3019 
3020 /**
3021  * target_if_spectral_populate_chwidth() - Helper routine to
3022  * populate channel width for different Spectral modes
3023  *
3024  * @spectral: Pointer to Spectral object
3025  * @ch_width: Channel width array
3026  * @is_80_80_agile: Indicates whether 80+80 agile scan is requested
3027  *
3028  * Helper routine to populate channel width for different Spectral modes
3029  *
3030  * Return: QDF_STATUS
3031  */
3032 static QDF_STATUS
3033 target_if_spectral_populate_chwidth(struct target_if_spectral *spectral,
3034 				    enum phy_ch_width *ch_width,
3035 				    bool is_80_80_agile) {
3036 	struct wlan_objmgr_vdev *vdev;
3037 	enum spectral_scan_mode smode;
3038 	enum phy_ch_width vdev_ch_width;
3039 
3040 	smode = SPECTRAL_SCAN_MODE_NORMAL;
3041 	for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++)
3042 		ch_width[smode] = CH_WIDTH_INVALID;
3043 
3044 	if (!spectral) {
3045 		spectral_err("Spectral object is null");
3046 		return QDF_STATUS_E_INVAL;
3047 	}
3048 
3049 	vdev = target_if_spectral_get_vdev(spectral, SPECTRAL_SCAN_MODE_NORMAL);
3050 	if (!vdev) {
3051 		spectral_err("vdev is null");
3052 		return QDF_STATUS_E_FAILURE;
3053 	}
3054 
3055 	vdev_ch_width = target_if_vdev_get_ch_width(vdev);
3056 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
3057 	if (vdev_ch_width == CH_WIDTH_INVALID) {
3058 		spectral_err("Invalid channel width %d", vdev_ch_width);
3059 		return QDF_STATUS_E_FAILURE;
3060 	}
3061 
3062 	ch_width[SPECTRAL_SCAN_MODE_NORMAL] = vdev_ch_width;
3063 	ch_width[SPECTRAL_SCAN_MODE_AGILE] =
3064 		target_if_spectral_find_agile_width(spectral, vdev_ch_width,
3065 						    is_80_80_agile);
3066 
3067 	return QDF_STATUS_SUCCESS;
3068 }
3069 
3070 /**
3071  * target_if_spectral_is_valid_80p80_freq() - API to check whether given
3072  * (cfreq1, cfreq2) pair forms a valid 80+80 combination
3073  * @pdev: pointer to pdev
3074  * @cfreq1: center frequency 1
3075  * @cfreq2: center frequency 2
3076  *
3077  * API to check whether given (cfreq1, cfreq2) pair forms a valid 80+80
3078  * combination
3079  *
3080  * Return: true or false
3081  */
3082 static bool
3083 target_if_spectral_is_valid_80p80_freq(struct wlan_objmgr_pdev *pdev,
3084 				       uint32_t cfreq1, uint32_t cfreq2)
3085 {
3086 	struct ch_params ch_params;
3087 	enum channel_state chan_state1;
3088 	enum channel_state chan_state2;
3089 	struct wlan_objmgr_psoc *psoc;
3090 
3091 	qdf_assert_always(pdev);
3092 	psoc = wlan_pdev_get_psoc(pdev);
3093 	qdf_assert_always(psoc);
3094 
3095 	/* In restricted 80P80 MHz enabled, only one 80+80 MHz
3096 	 * channel is supported with cfreq=5690 and cfreq=5775.
3097 	 */
3098 	if (wlan_psoc_nif_fw_ext_cap_get(
3099 				psoc, WLAN_SOC_RESTRICTED_80P80_SUPPORT))
3100 		return CHAN_WITHIN_RESTRICTED_80P80(cfreq1, cfreq2);
3101 
3102 	ch_params.center_freq_seg1 = wlan_reg_freq_to_chan(pdev, cfreq2);
3103 	ch_params.mhz_freq_seg1 = cfreq2;
3104 	ch_params.ch_width = CH_WIDTH_80P80MHZ;
3105 	wlan_reg_set_channel_params_for_freq(pdev, cfreq1 - FREQ_OFFSET_10MHZ,
3106 					     0, &ch_params);
3107 
3108 	if (ch_params.ch_width != CH_WIDTH_80P80MHZ)
3109 		return false;
3110 
3111 	if (ch_params.mhz_freq_seg0 != cfreq1 ||
3112 	    ch_params.mhz_freq_seg1 != cfreq2)
3113 		return false;
3114 
3115 	chan_state1 = wlan_reg_get_5g_bonded_channel_state_for_freq(
3116 				pdev,
3117 				ch_params.mhz_freq_seg0 - FREQ_OFFSET_10MHZ,
3118 				CH_WIDTH_80MHZ);
3119 	if ((chan_state1 == CHANNEL_STATE_DISABLE) ||
3120 	    (chan_state1 == CHANNEL_STATE_INVALID))
3121 		return false;
3122 
3123 	chan_state2 = wlan_reg_get_5g_bonded_channel_state_for_freq(
3124 				pdev,
3125 				ch_params.mhz_freq_seg1 - FREQ_OFFSET_10MHZ,
3126 				CH_WIDTH_80MHZ);
3127 	if ((chan_state2 == CHANNEL_STATE_DISABLE) ||
3128 	    (chan_state2 == CHANNEL_STATE_INVALID))
3129 		return false;
3130 
3131 	if (abs(ch_params.mhz_freq_seg0 - ch_params.mhz_freq_seg1) <=
3132 	    FREQ_OFFSET_80MHZ)
3133 		return false;
3134 
3135 	return true;
3136 }
3137 
3138 /**
3139  * _target_if_set_spectral_config() - Set spectral config
3140  * @spectral:       Pointer to spectral object
3141  * @param: Spectral parameter id and value
3142  * @smode: Spectral scan mode
3143  * @err: Spectral error code
3144  *
3145  * API to set spectral configurations
3146  *
3147  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
3148  */
3149 static QDF_STATUS
3150 _target_if_set_spectral_config(struct target_if_spectral *spectral,
3151 			       const struct spectral_cp_param *param,
3152 			       const enum spectral_scan_mode smode,
3153 			       enum spectral_cp_error_code *err)
3154 {
3155 	struct spectral_config params;
3156 	struct target_if_spectral_ops *p_sops;
3157 	struct spectral_config *sparams;
3158 	QDF_STATUS status;
3159 	bool is_overlapping;
3160 	uint16_t agile_cfreq;
3161 	bool is_valid_chan;
3162 	struct spectral_param_min_max *param_min_max;
3163 	enum phy_ch_width ch_width[SPECTRAL_SCAN_MODE_MAX];
3164 	enum spectral_scan_mode m;
3165 	struct spectral_config_frequency center_freq = {0};
3166 
3167 	if (!err) {
3168 		spectral_err("Error code argument is null");
3169 		QDF_ASSERT(0);
3170 		return QDF_STATUS_E_FAILURE;
3171 	}
3172 	*err = SPECTRAL_SCAN_ERR_INVALID;
3173 
3174 	if (!param) {
3175 		spectral_err("Parameter object is null");
3176 		return QDF_STATUS_E_FAILURE;
3177 	}
3178 
3179 	if (!spectral) {
3180 		spectral_err("spectral object is NULL");
3181 		return QDF_STATUS_E_FAILURE;
3182 	}
3183 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
3184 	param_min_max = &spectral->param_min_max;
3185 
3186 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
3187 		spectral_err("Invalid Spectral mode %u", smode);
3188 		*err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED;
3189 		return QDF_STATUS_E_FAILURE;
3190 	}
3191 
3192 	sparams = &spectral->params[smode];
3193 	m = SPECTRAL_SCAN_MODE_NORMAL;
3194 	for (; m < SPECTRAL_SCAN_MODE_MAX; m++)
3195 		ch_width[m] = CH_WIDTH_INVALID;
3196 
3197 	if (!spectral->params_valid[smode]) {
3198 		target_if_spectral_info_read(spectral,
3199 					     smode,
3200 					     TARGET_IF_SPECTRAL_INFO_PARAMS,
3201 					     &spectral->params[smode],
3202 					     sizeof(spectral->params[smode]));
3203 		spectral->params_valid[smode] = true;
3204 	}
3205 
3206 	switch (param->id) {
3207 	case SPECTRAL_PARAM_FFT_PERIOD:
3208 		sparams->ss_fft_period = param->value;
3209 		break;
3210 	case SPECTRAL_PARAM_SCAN_PERIOD:
3211 		sparams->ss_period = param->value;
3212 		break;
3213 	case SPECTRAL_PARAM_SCAN_COUNT:
3214 		sparams->ss_count = param->value;
3215 		break;
3216 	case SPECTRAL_PARAM_SHORT_REPORT:
3217 		sparams->ss_short_report = (!!param->value) ? true : false;
3218 		break;
3219 	case SPECTRAL_PARAM_SPECT_PRI:
3220 		sparams->ss_spectral_pri = (!!param->value) ? true : false;
3221 		break;
3222 	case SPECTRAL_PARAM_FFT_SIZE:
3223 		status = target_if_spectral_populate_chwidth
3224 			(spectral, ch_width, spectral->params
3225 			 [SPECTRAL_SCAN_MODE_AGILE].ss_frequency.cfreq2 > 0);
3226 		if (QDF_IS_STATUS_ERROR(status))
3227 			return QDF_STATUS_E_FAILURE;
3228 		if ((param->value < param_min_max->fft_size_min) ||
3229 		    (param->value > param_min_max->fft_size_max
3230 		    [ch_width[smode]])) {
3231 			*err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
3232 			return QDF_STATUS_E_FAILURE;
3233 		}
3234 		sparams->ss_fft_size = param->value;
3235 		break;
3236 	case SPECTRAL_PARAM_GC_ENA:
3237 		sparams->ss_gc_ena = !!param->value;
3238 		break;
3239 	case SPECTRAL_PARAM_RESTART_ENA:
3240 		sparams->ss_restart_ena = !!param->value;
3241 		break;
3242 	case SPECTRAL_PARAM_NOISE_FLOOR_REF:
3243 		sparams->ss_noise_floor_ref = param->value;
3244 		break;
3245 	case SPECTRAL_PARAM_INIT_DELAY:
3246 		sparams->ss_init_delay = param->value;
3247 		break;
3248 	case SPECTRAL_PARAM_NB_TONE_THR:
3249 		sparams->ss_nb_tone_thr = param->value;
3250 		break;
3251 	case SPECTRAL_PARAM_STR_BIN_THR:
3252 		sparams->ss_str_bin_thr = param->value;
3253 		break;
3254 	case SPECTRAL_PARAM_WB_RPT_MODE:
3255 		sparams->ss_wb_rpt_mode = !!param->value;
3256 		break;
3257 	case SPECTRAL_PARAM_RSSI_RPT_MODE:
3258 		sparams->ss_rssi_rpt_mode = !!param->value;
3259 		break;
3260 	case SPECTRAL_PARAM_RSSI_THR:
3261 		sparams->ss_rssi_thr = param->value;
3262 		break;
3263 	case SPECTRAL_PARAM_PWR_FORMAT:
3264 		sparams->ss_pwr_format = !!param->value;
3265 		break;
3266 	case SPECTRAL_PARAM_RPT_MODE:
3267 		if ((param->value < SPECTRAL_PARAM_RPT_MODE_MIN) ||
3268 		    (param->value > SPECTRAL_PARAM_RPT_MODE_MAX)) {
3269 			*err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
3270 			return QDF_STATUS_E_FAILURE;
3271 		}
3272 		sparams->ss_rpt_mode = param->value;
3273 		break;
3274 	case SPECTRAL_PARAM_BIN_SCALE:
3275 		sparams->ss_bin_scale = param->value;
3276 		break;
3277 	case SPECTRAL_PARAM_DBM_ADJ:
3278 		sparams->ss_dbm_adj = !!param->value;
3279 		break;
3280 	case SPECTRAL_PARAM_CHN_MASK:
3281 		sparams->ss_chn_mask = param->value;
3282 		break;
3283 	case SPECTRAL_PARAM_FREQUENCY:
3284 		status = target_if_spectral_populate_chwidth(
3285 				spectral, ch_width, param->freq.cfreq2 > 0);
3286 		if (QDF_IS_STATUS_ERROR(status)) {
3287 			spectral_err("Failed to populate channel width");
3288 			return QDF_STATUS_E_FAILURE;
3289 		}
3290 
3291 		if (ch_width[smode] != CH_WIDTH_80P80MHZ &&
3292 		    param->freq.cfreq2) {
3293 			*err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
3294 			spectral_err("Non zero cfreq2 expected for 80p80 only");
3295 			return QDF_STATUS_E_INVAL;
3296 		}
3297 
3298 		if (ch_width[smode] == CH_WIDTH_80P80MHZ &&
3299 		    !param->freq.cfreq2) {
3300 			*err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
3301 			spectral_err("Non zero cfreq2 expected for 80p80");
3302 			return QDF_STATUS_E_INVAL;
3303 		}
3304 
3305 		status = target_if_is_center_freq_of_any_chan
3306 				(spectral->pdev_obj, param->freq.cfreq1,
3307 				 &is_valid_chan);
3308 		if (QDF_IS_STATUS_ERROR(status))
3309 			return QDF_STATUS_E_FAILURE;
3310 
3311 		if (is_valid_chan) {
3312 			status = target_if_calculate_center_freq(
3313 							spectral, ch_width,
3314 							param->freq.cfreq1,
3315 							&agile_cfreq);
3316 			if (QDF_IS_STATUS_ERROR(status)) {
3317 				*err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
3318 				return QDF_STATUS_E_FAILURE;
3319 			}
3320 		} else {
3321 			bool is_valid_agile_cfreq;
3322 
3323 			status = target_if_validate_center_freq
3324 				(spectral, ch_width, param->freq.cfreq1,
3325 				 &is_valid_agile_cfreq);
3326 			if (QDF_IS_STATUS_ERROR(status))
3327 				return QDF_STATUS_E_FAILURE;
3328 
3329 			if (!is_valid_agile_cfreq) {
3330 				*err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
3331 				spectral_err("Invalid agile center frequency");
3332 				return QDF_STATUS_E_FAILURE;
3333 			}
3334 
3335 			agile_cfreq = param->freq.cfreq1;
3336 		}
3337 		center_freq.cfreq1 = agile_cfreq;
3338 
3339 		if (ch_width[smode] == CH_WIDTH_80P80MHZ) {
3340 			status = target_if_is_center_freq_of_any_chan
3341 					(spectral->pdev_obj, param->freq.cfreq2,
3342 					 &is_valid_chan);
3343 			if (QDF_IS_STATUS_ERROR(status))
3344 				return QDF_STATUS_E_FAILURE;
3345 
3346 			if (is_valid_chan) {
3347 				status = target_if_calculate_center_freq(
3348 						spectral, ch_width,
3349 						param->freq.cfreq2,
3350 						&agile_cfreq);
3351 				if (QDF_IS_STATUS_ERROR(status)) {
3352 					*err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
3353 					return QDF_STATUS_E_FAILURE;
3354 				}
3355 			} else {
3356 				bool is_valid_agile_cfreq;
3357 
3358 				status = target_if_validate_center_freq
3359 					(spectral, ch_width, param->freq.cfreq2,
3360 					 &is_valid_agile_cfreq);
3361 				if (QDF_IS_STATUS_ERROR(status))
3362 					return QDF_STATUS_E_FAILURE;
3363 
3364 				if (!is_valid_agile_cfreq) {
3365 					*err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
3366 					spectral_err("Invalid agile center frequency");
3367 					return QDF_STATUS_E_FAILURE;
3368 				}
3369 
3370 				agile_cfreq = param->freq.cfreq2;
3371 			}
3372 			center_freq.cfreq2 = agile_cfreq;
3373 		}
3374 
3375 		status = target_if_is_agile_span_overlap_with_operating_span
3376 				(spectral, ch_width,
3377 				 &center_freq, &is_overlapping);
3378 		if (QDF_IS_STATUS_ERROR(status))
3379 			return QDF_STATUS_E_FAILURE;
3380 
3381 		if (is_overlapping) {
3382 			spectral_err("Agile freq %u, %u overlaps with operating span",
3383 				     center_freq.cfreq1, center_freq.cfreq2);
3384 			*err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
3385 			return QDF_STATUS_E_FAILURE;
3386 		}
3387 
3388 		if (ch_width[smode] == CH_WIDTH_80P80MHZ) {
3389 			bool is_valid_80p80;
3390 
3391 			is_valid_80p80 = target_if_spectral_is_valid_80p80_freq(
3392 						spectral->pdev_obj,
3393 						center_freq.cfreq1,
3394 						center_freq.cfreq2);
3395 
3396 			if (!is_valid_80p80) {
3397 				spectral_err("Agile freq %u, %u is invalid 80+80 combination",
3398 					     center_freq.cfreq1,
3399 					     center_freq.cfreq2);
3400 				*err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
3401 				return QDF_STATUS_E_FAILURE;
3402 			}
3403 		}
3404 
3405 		sparams->ss_frequency.cfreq1 = center_freq.cfreq1;
3406 		sparams->ss_frequency.cfreq2 = center_freq.cfreq2;
3407 
3408 		break;
3409 	}
3410 
3411 	p_sops->configure_spectral(spectral, sparams, smode);
3412 	/* only to validate the writes */
3413 	p_sops->get_spectral_config(spectral, &params, smode);
3414 	return QDF_STATUS_SUCCESS;
3415 }
3416 
3417 QDF_STATUS
3418 target_if_set_spectral_config(struct wlan_objmgr_pdev *pdev,
3419 			      const struct spectral_cp_param *param,
3420 			      const enum spectral_scan_mode smode,
3421 			      enum spectral_cp_error_code *err)
3422 {
3423 	enum spectral_scan_mode mode = SPECTRAL_SCAN_MODE_NORMAL;
3424 	struct target_if_spectral *spectral;
3425 	QDF_STATUS status;
3426 
3427 	if (!err) {
3428 		spectral_err("Error code argument is null");
3429 		QDF_ASSERT(0);
3430 		return QDF_STATUS_E_FAILURE;
3431 	}
3432 	*err = SPECTRAL_SCAN_ERR_INVALID;
3433 
3434 	if (!pdev) {
3435 		spectral_err("pdev object is NULL");
3436 		return QDF_STATUS_E_FAILURE;
3437 	}
3438 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
3439 	if (!spectral) {
3440 		spectral_err("spectral object is NULL");
3441 		return QDF_STATUS_E_FAILURE;
3442 	}
3443 
3444 	if (!param) {
3445 		spectral_err("parameter object is NULL");
3446 		return QDF_STATUS_E_FAILURE;
3447 	}
3448 
3449 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
3450 		spectral_err("Invalid Spectral mode %u", smode);
3451 		*err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED;
3452 		return QDF_STATUS_E_FAILURE;
3453 	}
3454 
3455 	if (!spectral->properties[smode][param->id].supported) {
3456 		spectral_err("Spectral parameter(%u) unsupported for mode %u",
3457 			     param->id, smode);
3458 		*err = SPECTRAL_SCAN_ERR_PARAM_UNSUPPORTED;
3459 		return QDF_STATUS_E_FAILURE;
3460 	}
3461 
3462 	if (spectral->properties[smode][param->id].common_all_modes) {
3463 		spectral_warn("Setting Spectral parameter %u for all modes",
3464 			      param->id);
3465 		for (; mode < SPECTRAL_SCAN_MODE_MAX; mode++) {
3466 			status = _target_if_set_spectral_config
3467 						(spectral, param, mode, err);
3468 			if (QDF_IS_STATUS_ERROR(status))
3469 				return QDF_STATUS_E_FAILURE;
3470 		}
3471 		return QDF_STATUS_SUCCESS;
3472 	}
3473 
3474 	return _target_if_set_spectral_config(spectral, param, smode, err);
3475 }
3476 
3477 /**
3478  * target_if_get_fft_bin_count() - Get fft bin count for a given fft length
3479  * @fft_len: FFT length
3480  * @pdev: Pointer to pdev object
3481  *
3482  * API to get fft bin count for a given fft length
3483  *
3484  * Return: FFt bin count
3485  */
3486 static int
3487 target_if_get_fft_bin_count(int fft_len)
3488 {
3489 	int bin_count = 0;
3490 
3491 	switch (fft_len) {
3492 	case 5:
3493 		bin_count = 16;
3494 		break;
3495 	case 6:
3496 		bin_count = 32;
3497 		break;
3498 	case 7:
3499 		bin_count = 64;
3500 		break;
3501 	case 8:
3502 		bin_count = 128;
3503 		break;
3504 	case 9:
3505 		bin_count = 256;
3506 		break;
3507 	default:
3508 		break;
3509 	}
3510 
3511 	return bin_count;
3512 }
3513 
3514 /**
3515  * target_if_init_upper_lower_flags() - Initializes control and extension
3516  * segment flags
3517  * @spectral: pointer to target if spectral object
3518  * @smode: Spectral scan mode
3519  *
3520  * API to initialize the control and extension flags with the lower/upper
3521  * segment based on the HT mode
3522  *
3523  * Return: FFt bin count
3524  */
3525 static void
3526 target_if_init_upper_lower_flags(struct target_if_spectral *spectral,
3527 				 enum spectral_scan_mode smode)
3528 {
3529 	int current_channel = 0;
3530 	int ext_channel = 0;
3531 	struct target_if_spectral_ops *p_sops =
3532 		GET_TARGET_IF_SPECTRAL_OPS(spectral);
3533 
3534 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
3535 		spectral_err("Invalid Spectral mode %u", smode);
3536 		return;
3537 	}
3538 	current_channel = p_sops->get_current_channel(spectral, smode);
3539 	ext_channel = p_sops->get_extension_channel(spectral, smode);
3540 
3541 	if ((current_channel == 0) || (ext_channel == 0))
3542 		return;
3543 
3544 	if (spectral->sc_spectral_20_40_mode) {
3545 		/* HT40 mode */
3546 		if (ext_channel < current_channel) {
3547 			spectral->lower_is_extension = 1;
3548 			spectral->upper_is_control = 1;
3549 			spectral->lower_is_control = 0;
3550 			spectral->upper_is_extension = 0;
3551 		} else {
3552 			spectral->lower_is_extension = 0;
3553 			spectral->upper_is_control = 0;
3554 			spectral->lower_is_control = 1;
3555 			spectral->upper_is_extension = 1;
3556 		}
3557 	} else {
3558 		/* HT20 mode, lower is always control */
3559 		spectral->lower_is_extension = 0;
3560 		spectral->upper_is_control = 0;
3561 		spectral->lower_is_control = 1;
3562 		spectral->upper_is_extension = 0;
3563 	}
3564 }
3565 
3566 /**
3567  * target_if_get_spectral_config() - Get spectral configuration
3568  * @pdev: Pointer to pdev object
3569  * @param: Pointer to spectral_config structure in which the configuration
3570  * should be returned
3571  * @smode: Spectral scan mode
3572  *
3573  * API to get the current spectral configuration
3574  *
3575  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
3576  */
3577 QDF_STATUS
3578 target_if_get_spectral_config(struct wlan_objmgr_pdev *pdev,
3579 			      struct spectral_config *param,
3580 			      enum spectral_scan_mode smode)
3581 {
3582 	struct target_if_spectral_ops *p_sops = NULL;
3583 	struct target_if_spectral *spectral = NULL;
3584 
3585 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
3586 
3587 	if (!spectral) {
3588 		spectral_err("SPECTRAL : Module doesn't exist");
3589 		return QDF_STATUS_E_FAILURE;
3590 	}
3591 
3592 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
3593 
3594 	if (!p_sops) {
3595 		spectral_err("p_sops is null");
3596 		return QDF_STATUS_E_FAILURE;
3597 	}
3598 
3599 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
3600 		spectral_err("Invalid Spectral mode %u", smode);
3601 		return QDF_STATUS_E_FAILURE;
3602 	}
3603 
3604 	qdf_mem_zero(param, sizeof(struct spectral_config));
3605 	p_sops->get_spectral_config(spectral, param, smode);
3606 
3607 	return QDF_STATUS_SUCCESS;
3608 }
3609 
3610 /**
3611  * target_if_spectral_scan_enable_params() - Enable use of desired Spectral
3612  *                                           parameters
3613  * @spectral: Pointer to Spectral target_if internal private data
3614  * @spectral_params: Pointer to Spectral parameters
3615  * @smode: Spectral scan mode
3616  * @err: Spectral error code
3617  *
3618  * Enable use of desired Spectral parameters by configuring them into HW, and
3619  * starting Spectral scan
3620  *
3621  * Return: 0 on success, 1 on failure
3622  */
3623 int
3624 target_if_spectral_scan_enable_params(struct target_if_spectral *spectral,
3625 				      struct spectral_config *spectral_params,
3626 				      enum spectral_scan_mode smode,
3627 				      enum spectral_cp_error_code *err)
3628 {
3629 	int extension_channel = 0;
3630 	int current_channel = 0;
3631 	struct target_if_spectral_ops *p_sops = NULL;
3632 	QDF_STATUS status;
3633 	struct wlan_objmgr_pdev *pdev;
3634 	struct wlan_objmgr_psoc *psoc;
3635 
3636 	if (!spectral) {
3637 		spectral_err("Spectral LMAC object is NULL");
3638 		return 1;
3639 	}
3640 
3641 	pdev =  spectral->pdev_obj;
3642 	if (!pdev) {
3643 		spectral_err("pdev is null");
3644 		return QDF_STATUS_E_INVAL;
3645 	}
3646 
3647 	psoc = wlan_pdev_get_psoc(pdev);
3648 	if (!psoc) {
3649 		spectral_err("psoc is null");
3650 		return QDF_STATUS_E_INVAL;
3651 	}
3652 
3653 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
3654 		spectral_err("Invalid Spectral mode %u", smode);
3655 		return 1;
3656 	}
3657 
3658 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
3659 
3660 	if (!p_sops) {
3661 		spectral_err("p_sops is NULL");
3662 		return 1;
3663 	}
3664 
3665 	spectral->sc_spectral_noise_pwr_cal =
3666 	    spectral_params->ss_spectral_pri ? 1 : 0;
3667 
3668 	/* check if extension channel is present */
3669 	extension_channel = p_sops->get_extension_channel(spectral, smode);
3670 	current_channel = p_sops->get_current_channel(spectral, smode);
3671 
3672 	status = target_if_spectral_populate_chwidth(
3673 			spectral, spectral->ch_width,
3674 			spectral->params[SPECTRAL_SCAN_MODE_AGILE].
3675 			ss_frequency.cfreq2 > 0);
3676 	if (QDF_IS_STATUS_ERROR(status)) {
3677 		spectral_err("Failed to get channel widths");
3678 		return 1;
3679 	}
3680 
3681 	if (spectral->capability.advncd_spectral_cap) {
3682 		spectral->lb_edge_extrabins = 0;
3683 		spectral->rb_edge_extrabins = 0;
3684 
3685 		if (spectral->is_lb_edge_extrabins_format &&
3686 		    spectral->params[smode].ss_rpt_mode == 2) {
3687 			spectral->lb_edge_extrabins = 4;
3688 		}
3689 
3690 		if (spectral->is_rb_edge_extrabins_format &&
3691 		    spectral->params[smode].ss_rpt_mode == 2) {
3692 			spectral->rb_edge_extrabins = 4;
3693 		}
3694 
3695 		if (spectral->ch_width[smode] == CH_WIDTH_20MHZ) {
3696 			spectral->sc_spectral_20_40_mode = 0;
3697 
3698 			spectral->spectral_numbins =
3699 			    target_if_get_fft_bin_count(
3700 				spectral->params[smode].ss_fft_size);
3701 			spectral->spectral_fft_len =
3702 			    target_if_get_fft_bin_count(
3703 				spectral->params[smode].ss_fft_size);
3704 			spectral->spectral_data_len =
3705 			    target_if_get_fft_bin_count(
3706 				spectral->params[smode].ss_fft_size);
3707 			/*
3708 			 * Initialize classifier params to be sent to user
3709 			 * space classifier
3710 			 */
3711 			spectral->classifier_params.lower_chan_in_mhz =
3712 			    current_channel;
3713 			spectral->classifier_params.upper_chan_in_mhz = 0;
3714 
3715 		} else if (spectral->ch_width[smode] == CH_WIDTH_40MHZ) {
3716 			/* TODO : Remove this variable */
3717 			spectral->sc_spectral_20_40_mode = 1;
3718 			spectral->spectral_numbins =
3719 			    target_if_get_fft_bin_count(
3720 				spectral->params[smode].ss_fft_size);
3721 			spectral->spectral_fft_len =
3722 			    target_if_get_fft_bin_count(
3723 				spectral->params[smode].ss_fft_size);
3724 			spectral->spectral_data_len =
3725 			    target_if_get_fft_bin_count(
3726 				spectral->params[smode].ss_fft_size);
3727 
3728 			/*
3729 			 * Initialize classifier params to be sent to user
3730 			 * space classifier
3731 			 */
3732 			if (extension_channel < current_channel) {
3733 				spectral->classifier_params.lower_chan_in_mhz =
3734 				    extension_channel;
3735 				spectral->classifier_params.upper_chan_in_mhz =
3736 				    current_channel;
3737 			} else {
3738 				spectral->classifier_params.lower_chan_in_mhz =
3739 				    current_channel;
3740 				spectral->classifier_params.upper_chan_in_mhz =
3741 				    extension_channel;
3742 			}
3743 
3744 		} else if (spectral->ch_width[smode] == CH_WIDTH_80MHZ) {
3745 			/* Set the FFT Size */
3746 			/* TODO : Remove this variable */
3747 			spectral->sc_spectral_20_40_mode = 0;
3748 			spectral->spectral_numbins =
3749 			    target_if_get_fft_bin_count(
3750 				spectral->params[smode].ss_fft_size);
3751 			spectral->spectral_fft_len =
3752 			    target_if_get_fft_bin_count(
3753 				spectral->params[smode].ss_fft_size);
3754 			spectral->spectral_data_len =
3755 			    target_if_get_fft_bin_count(
3756 				spectral->params[smode].ss_fft_size);
3757 
3758 			/*
3759 			 * Initialize classifier params to be sent to user
3760 			 * space classifier
3761 			 */
3762 			spectral->classifier_params.lower_chan_in_mhz =
3763 			    current_channel;
3764 			spectral->classifier_params.upper_chan_in_mhz = 0;
3765 
3766 			/*
3767 			 * Initialize classifier params to be sent to user
3768 			 * space classifier
3769 			 */
3770 			if (extension_channel < current_channel) {
3771 				spectral->classifier_params.lower_chan_in_mhz =
3772 				    extension_channel;
3773 				spectral->classifier_params.upper_chan_in_mhz =
3774 				    current_channel;
3775 			} else {
3776 				spectral->classifier_params.lower_chan_in_mhz =
3777 				    current_channel;
3778 				spectral->classifier_params.upper_chan_in_mhz =
3779 				    extension_channel;
3780 			}
3781 
3782 		} else if (is_ch_width_160_or_80p80(
3783 			   spectral->ch_width[smode])) {
3784 			/* Set the FFT Size */
3785 
3786 			/* The below applies to both 160 and 80+80 cases */
3787 
3788 			/* TODO : Remove this variable */
3789 			spectral->sc_spectral_20_40_mode = 0;
3790 			spectral->spectral_numbins =
3791 			    target_if_get_fft_bin_count(
3792 				spectral->params[smode].ss_fft_size);
3793 			spectral->spectral_fft_len =
3794 			    target_if_get_fft_bin_count(
3795 				spectral->params[smode].ss_fft_size);
3796 			spectral->spectral_data_len =
3797 			    target_if_get_fft_bin_count(
3798 				spectral->params[smode].ss_fft_size);
3799 
3800 			/*
3801 			 * Initialize classifier params to be sent to user
3802 			 * space classifier
3803 			 */
3804 			spectral->classifier_params.lower_chan_in_mhz =
3805 			    current_channel;
3806 			spectral->classifier_params.upper_chan_in_mhz = 0;
3807 
3808 			/*
3809 			 * Initialize classifier params to be sent to user
3810 			 * space classifier
3811 			 */
3812 			if (extension_channel < current_channel) {
3813 				spectral->classifier_params.lower_chan_in_mhz =
3814 				    extension_channel;
3815 				spectral->classifier_params.upper_chan_in_mhz =
3816 				    current_channel;
3817 			} else {
3818 				spectral->classifier_params.lower_chan_in_mhz =
3819 				    current_channel;
3820 				spectral->classifier_params.upper_chan_in_mhz =
3821 				    extension_channel;
3822 			}
3823 		}
3824 
3825 		if (spectral->spectral_numbins) {
3826 			spectral->spectral_numbins +=
3827 			    spectral->lb_edge_extrabins;
3828 			spectral->spectral_numbins +=
3829 			    spectral->rb_edge_extrabins;
3830 		}
3831 
3832 		if (spectral->spectral_fft_len) {
3833 			spectral->spectral_fft_len +=
3834 			    spectral->lb_edge_extrabins;
3835 			spectral->spectral_fft_len +=
3836 			    spectral->rb_edge_extrabins;
3837 		}
3838 
3839 		if (spectral->spectral_data_len) {
3840 			spectral->spectral_data_len +=
3841 			    spectral->lb_edge_extrabins;
3842 			spectral->spectral_data_len +=
3843 			    spectral->rb_edge_extrabins;
3844 		}
3845 	} else {
3846 		/*
3847 		 * The decision to find 20/40 mode is found based on the
3848 		 * presence of extension channel
3849 		 * instead of channel width, as the channel width can
3850 		 * dynamically change
3851 		 */
3852 
3853 		if (extension_channel == 0) {
3854 			spectral->spectral_numbins = SPECTRAL_HT20_NUM_BINS;
3855 			spectral->spectral_dc_index = SPECTRAL_HT20_DC_INDEX;
3856 			spectral->spectral_fft_len = SPECTRAL_HT20_FFT_LEN;
3857 			spectral->spectral_data_len =
3858 			    SPECTRAL_HT20_TOTAL_DATA_LEN;
3859 			/* only valid in 20-40 mode */
3860 			spectral->spectral_lower_max_index_offset = -1;
3861 			/* only valid in 20-40 mode */
3862 			spectral->spectral_upper_max_index_offset = -1;
3863 			spectral->spectral_max_index_offset =
3864 			    spectral->spectral_fft_len + 2;
3865 			spectral->sc_spectral_20_40_mode = 0;
3866 
3867 			/*
3868 			 * Initialize classifier params to be sent to user
3869 			 * space classifier
3870 			 */
3871 			spectral->classifier_params.lower_chan_in_mhz =
3872 			    current_channel;
3873 			spectral->classifier_params.upper_chan_in_mhz = 0;
3874 
3875 		} else {
3876 			spectral->spectral_numbins =
3877 			    SPECTRAL_HT40_TOTAL_NUM_BINS;
3878 			spectral->spectral_fft_len = SPECTRAL_HT40_FFT_LEN;
3879 			spectral->spectral_data_len =
3880 			    SPECTRAL_HT40_TOTAL_DATA_LEN;
3881 			spectral->spectral_dc_index = SPECTRAL_HT40_DC_INDEX;
3882 			/* only valid in 20 mode */
3883 			spectral->spectral_max_index_offset = -1;
3884 			spectral->spectral_lower_max_index_offset =
3885 			    spectral->spectral_fft_len + 2;
3886 			spectral->spectral_upper_max_index_offset =
3887 			    spectral->spectral_fft_len + 5;
3888 			spectral->sc_spectral_20_40_mode = 1;
3889 
3890 			/*
3891 			 * Initialize classifier params to be sent to user
3892 			 * space classifier
3893 			 */
3894 			if (extension_channel < current_channel) {
3895 				spectral->classifier_params.lower_chan_in_mhz =
3896 				    extension_channel;
3897 				spectral->classifier_params.upper_chan_in_mhz =
3898 				    current_channel;
3899 			} else {
3900 				spectral->classifier_params.lower_chan_in_mhz =
3901 				    current_channel;
3902 				spectral->classifier_params.upper_chan_in_mhz =
3903 				    extension_channel;
3904 			}
3905 		}
3906 	}
3907 
3908 	spectral->send_single_packet = 0;
3909 	spectral->classifier_params.spectral_20_40_mode =
3910 	    spectral->sc_spectral_20_40_mode;
3911 	spectral->classifier_params.spectral_dc_index =
3912 	    spectral->spectral_dc_index;
3913 	spectral->spectral_sent_msg = 0;
3914 	spectral->classify_scan = 0;
3915 	spectral->num_spectral_data = 0;
3916 
3917 	if (!p_sops->is_spectral_active(spectral, smode)) {
3918 		p_sops->configure_spectral(spectral, spectral_params, smode);
3919 		spectral->rparams.marker[smode].is_valid = false;
3920 		p_sops->start_spectral_scan(spectral, smode, err);
3921 		spectral->timestamp_war.timestamp_war_offset[smode] = 0;
3922 		spectral->timestamp_war.last_fft_timestamp[smode] = 0;
3923 	}
3924 
3925 	/* get current spectral configuration */
3926 	p_sops->get_spectral_config(spectral, &spectral->params[smode], smode);
3927 
3928 	target_if_init_upper_lower_flags(spectral, smode);
3929 
3930 	return 0;
3931 }
3932 
3933 /**
3934  * target_if_is_aspectral_prohibited_by_adfs() - Is Agile Spectral prohibited by
3935  * Agile DFS
3936  * @psoc: Pointer to psoc
3937  * @object: Pointer to pdev
3938  * @arg: Pointer to flag which indicates whether Agile Spectral is prohibited
3939  *
3940  * This API checks whether Agile DFS is running on any of the pdevs. If so, it
3941  * indicates that Agile Spectral scan is prohibited by Agile DFS.
3942  *
3943  * Return: void
3944  */
3945 static void
3946 target_if_is_aspectral_prohibited_by_adfs(struct wlan_objmgr_psoc *psoc,
3947 					  void *object, void *arg)
3948 {
3949 	bool *is_aspectral_prohibited = arg;
3950 	struct wlan_objmgr_pdev *cur_pdev = object;
3951 	bool is_agile_dfs_enabled_cur_pdev = false;
3952 	QDF_STATUS status;
3953 
3954 	qdf_assert_always(is_aspectral_prohibited);
3955 	if (*is_aspectral_prohibited)
3956 		return;
3957 
3958 	qdf_assert_always(psoc);
3959 	qdf_assert_always(cur_pdev);
3960 
3961 	status = ucfg_dfs_get_agile_precac_enable
3962 				(cur_pdev,
3963 				 &is_agile_dfs_enabled_cur_pdev);
3964 	if (QDF_IS_STATUS_ERROR(status)) {
3965 		spectral_err("Get agile precac failed, prohibiting aSpectral");
3966 		*is_aspectral_prohibited = true;
3967 		return;
3968 	}
3969 
3970 	if (is_agile_dfs_enabled_cur_pdev) {
3971 		spectral_err("aDFS is in progress on one of the pdevs");
3972 		*is_aspectral_prohibited = true;
3973 	}
3974 }
3975 
3976 /**
3977  * target_if_get_curr_band() - Get current operating band of pdev
3978  *
3979  * @pdev: pointer to pdev object
3980  *
3981  * API to get current operating band of a given pdev.
3982  *
3983  * Return: if success enum reg_wifi_band, REG_BAND_UNKNOWN in case of failure
3984  */
3985 static enum reg_wifi_band
3986 target_if_get_curr_band(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id)
3987 {
3988 	struct wlan_objmgr_vdev *vdev;
3989 	int16_t chan_freq;
3990 	enum reg_wifi_band cur_band;
3991 
3992 	if (!pdev) {
3993 		spectral_err("pdev is NULL");
3994 		return REG_BAND_UNKNOWN;
3995 	}
3996 
3997 	if (vdev_id == WLAN_INVALID_VDEV_ID)
3998 		vdev = wlan_objmgr_pdev_get_first_vdev(pdev, WLAN_SPECTRAL_ID);
3999 	else
4000 		vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id,
4001 							    WLAN_SPECTRAL_ID);
4002 	if (!vdev) {
4003 		spectral_debug("vdev is NULL");
4004 		return REG_BAND_UNKNOWN;
4005 	}
4006 	chan_freq = target_if_vdev_get_chan_freq(vdev);
4007 	cur_band = wlan_reg_freq_to_band(chan_freq);
4008 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
4009 
4010 	return cur_band;
4011 }
4012 
4013 /**
4014  * target_if_is_agile_scan_active_in_5g() - Is Agile Spectral scan active on
4015  * any of the 5G pdevs
4016  * @psoc: Pointer to psoc
4017  * @object: Pointer to pdev
4018  * @arg: Pointer to flag which indicates whether Agile Spectral scan is in
4019  *       progress in any 5G pdevs
4020  *
4021  * Return: void
4022  */
4023 static void
4024 target_if_is_agile_scan_active_in_5g(struct wlan_objmgr_psoc *psoc,
4025 				     void *object, void *arg)
4026 {
4027 	enum reg_wifi_band band;
4028 	bool *is_agile_scan_inprog_5g_pdev = arg;
4029 	struct target_if_spectral *spectral;
4030 	struct wlan_objmgr_pdev *cur_pdev = object;
4031 	struct target_if_spectral_ops *p_sops;
4032 
4033 	if (*is_agile_scan_inprog_5g_pdev)
4034 		return;
4035 
4036 	spectral = get_target_if_spectral_handle_from_pdev(cur_pdev);
4037 	if (!spectral) {
4038 		spectral_err("target if spectral handle is NULL");
4039 		return;
4040 	}
4041 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
4042 
4043 	band = target_if_get_curr_band(
4044 			cur_pdev, spectral->vdev_id[SPECTRAL_SCAN_MODE_AGILE]);
4045 	if (band == REG_BAND_UNKNOWN) {
4046 		spectral_debug("Failed to get current band");
4047 		return;
4048 	}
4049 
4050 	if (band == REG_BAND_5G &&
4051 	    p_sops->is_spectral_active(spectral, SPECTRAL_SCAN_MODE_AGILE))
4052 		*is_agile_scan_inprog_5g_pdev = true;
4053 }
4054 
4055 /**
4056  * target_if_is_agile_supported_cur_chmask() - Is Agile Spectral scan supported
4057  * for current vdev rx chainmask.
4058  *
4059  * @spectral: Pointer to Spectral object
4060  * @is_supported: Pointer to is_supported
4061  *
4062  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
4063  */
4064 static QDF_STATUS
4065 target_if_is_agile_supported_cur_chmask(struct target_if_spectral *spectral,
4066 					bool *is_supported)
4067 {
4068 	struct wlan_objmgr_vdev *vdev;
4069 	uint8_t vdev_rxchainmask;
4070 	struct wlan_objmgr_psoc *psoc;
4071 	struct wlan_objmgr_pdev *pdev;
4072 	struct target_psoc_info *tgt_psoc_info;
4073 	struct wlan_psoc_host_service_ext_param *ext_svc_param;
4074 	struct wlan_psoc_host_mac_phy_caps *mac_phy_cap_arr = NULL;
4075 	struct wlan_psoc_host_mac_phy_caps *mac_phy_cap = NULL;
4076 	struct wlan_psoc_host_chainmask_table *table;
4077 	int j;
4078 	uint32_t table_id;
4079 	enum phy_ch_width ch_width;
4080 	uint8_t pdev_id;
4081 
4082 	if (!spectral) {
4083 		spectral_err("spectral target if object is null");
4084 		return QDF_STATUS_E_FAILURE;
4085 	}
4086 
4087 	if (!is_supported) {
4088 		spectral_err("is supported argument is null");
4089 		return QDF_STATUS_E_FAILURE;
4090 	}
4091 
4092 	if (spectral->spectral_gen <= SPECTRAL_GEN2) {
4093 		spectral_err("HW Agile mode is not supported up to gen 2");
4094 		return QDF_STATUS_E_FAILURE;
4095 	}
4096 
4097 	pdev = spectral->pdev_obj;
4098 	if (!pdev) {
4099 		spectral_err("pdev is null");
4100 		return QDF_STATUS_E_FAILURE;
4101 	}
4102 
4103 	psoc = wlan_pdev_get_psoc(pdev);
4104 	if (!psoc) {
4105 		spectral_err("psoc is null");
4106 		return QDF_STATUS_E_FAILURE;
4107 	}
4108 
4109 	vdev = target_if_spectral_get_vdev(spectral, SPECTRAL_SCAN_MODE_AGILE);
4110 	if (!vdev) {
4111 		spectral_err("First vdev is NULL");
4112 		return QDF_STATUS_E_FAILURE;
4113 	}
4114 
4115 	vdev_rxchainmask = wlan_vdev_mlme_get_rxchainmask(vdev);
4116 	if (!vdev_rxchainmask) {
4117 		spectral_err("vdev rx chainmask is zero");
4118 		wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
4119 		return QDF_STATUS_E_FAILURE;
4120 	}
4121 
4122 	ch_width = target_if_vdev_get_ch_width(vdev);
4123 	if (ch_width == CH_WIDTH_INVALID) {
4124 		spectral_err("Invalid channel width");
4125 		wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
4126 		return QDF_STATUS_E_FAILURE;
4127 	}
4128 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
4129 
4130 	tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc);
4131 	if (!tgt_psoc_info) {
4132 		spectral_err("target_psoc_info is null");
4133 		return QDF_STATUS_E_FAILURE;
4134 	}
4135 
4136 	ext_svc_param = target_psoc_get_service_ext_param(tgt_psoc_info);
4137 	if (!ext_svc_param) {
4138 		spectral_err("Extended service ready param null");
4139 		return QDF_STATUS_E_FAILURE;
4140 	}
4141 	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
4142 
4143 	mac_phy_cap_arr = target_psoc_get_mac_phy_cap(tgt_psoc_info);
4144 	if (!mac_phy_cap_arr) {
4145 		spectral_err("mac phy cap array is null");
4146 		return QDF_STATUS_E_FAILURE;
4147 	}
4148 
4149 	mac_phy_cap = &mac_phy_cap_arr[pdev_id];
4150 	if (!mac_phy_cap) {
4151 		spectral_err("mac phy cap is null");
4152 		return QDF_STATUS_E_FAILURE;
4153 	}
4154 
4155 	table_id = mac_phy_cap->chainmask_table_id;
4156 	table =  &ext_svc_param->chainmask_table[table_id];
4157 	if (!table) {
4158 		spectral_err("chainmask table not found");
4159 		return QDF_STATUS_E_FAILURE;
4160 	}
4161 
4162 	for (j = 0; j < table->num_valid_chainmasks; j++) {
4163 		if (table->cap_list[j].chainmask == vdev_rxchainmask) {
4164 			if (ch_width <= CH_WIDTH_80MHZ)
4165 				*is_supported =
4166 					table->cap_list[j].supports_aSpectral;
4167 			else
4168 				*is_supported =
4169 				      table->cap_list[j].supports_aSpectral_160;
4170 			break;
4171 		}
4172 	}
4173 
4174 	if (j == table->num_valid_chainmasks) {
4175 		spectral_err("vdev rx chainmask %u not found in table id = %u",
4176 			     vdev_rxchainmask, table_id);
4177 		return QDF_STATUS_E_FAILURE;
4178 	}
4179 
4180 	return QDF_STATUS_SUCCESS;
4181 }
4182 
4183 QDF_STATUS
4184 target_if_start_spectral_scan(struct wlan_objmgr_pdev *pdev,
4185 			      uint8_t vdev_id,
4186 			      const enum spectral_scan_mode smode,
4187 			      enum spectral_cp_error_code *err)
4188 {
4189 	struct target_if_spectral_ops *p_sops;
4190 	struct target_if_spectral *spectral;
4191 	struct wlan_objmgr_psoc *psoc;
4192 	enum reg_wifi_band band;
4193 
4194 	if (!err) {
4195 		spectral_err("Error code argument is null");
4196 		QDF_ASSERT(0);
4197 		return QDF_STATUS_E_FAILURE;
4198 	}
4199 	*err = SPECTRAL_SCAN_ERR_INVALID;
4200 
4201 	if (!pdev) {
4202 		spectral_err("pdev object is NUll");
4203 		return QDF_STATUS_E_FAILURE;
4204 	}
4205 
4206 	psoc = wlan_pdev_get_psoc(pdev);
4207 	if (!psoc) {
4208 		spectral_err("psoc is null");
4209 		return QDF_STATUS_E_FAILURE;
4210 	}
4211 
4212 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
4213 		*err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED;
4214 		spectral_err("Invalid Spectral mode %u", smode);
4215 		return QDF_STATUS_E_FAILURE;
4216 	}
4217 
4218 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
4219 	if (!spectral) {
4220 		spectral_err("Spectral LMAC object is NUll");
4221 		return QDF_STATUS_E_FAILURE;
4222 	}
4223 
4224 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
4225 	if (!p_sops) {
4226 		spectral_err("p_sops is null");
4227 		return QDF_STATUS_E_FAILURE;
4228 	}
4229 
4230 	if (p_sops->is_spectral_active(spectral, smode)) {
4231 		spectral_err("spectral in progress in current pdev, mode %d",
4232 			     smode);
4233 		return QDF_STATUS_E_FAILURE;
4234 	}
4235 	spectral->vdev_id[smode] = vdev_id;
4236 
4237 	if (smode == SPECTRAL_SCAN_MODE_AGILE) {
4238 		QDF_STATUS status;
4239 		bool is_supported = false;
4240 
4241 		status = target_if_is_agile_supported_cur_chmask(spectral,
4242 								 &is_supported);
4243 		if (QDF_IS_STATUS_ERROR(status)) {
4244 			*err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED;
4245 			return QDF_STATUS_E_FAILURE;
4246 		}
4247 
4248 		if (!is_supported) {
4249 			spectral_err("aSpectral unsupported for cur chainmask");
4250 			*err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED;
4251 			return QDF_STATUS_E_FAILURE;
4252 		}
4253 	}
4254 
4255 	band = target_if_get_curr_band(spectral->pdev_obj, vdev_id);
4256 	if (band == REG_BAND_UNKNOWN) {
4257 		spectral_err("Failed to get current band");
4258 		return QDF_STATUS_E_FAILURE;
4259 	}
4260 	if ((band == REG_BAND_5G) && (smode == SPECTRAL_SCAN_MODE_AGILE)) {
4261 		struct target_psoc_info *tgt_hdl;
4262 		enum wmi_host_hw_mode_config_type mode;
4263 		bool is_agile_scan_inprog_5g_pdev;
4264 
4265 		tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc);
4266 		if (!tgt_hdl) {
4267 			target_if_err("target_psoc_info is null");
4268 			return QDF_STATUS_E_FAILURE;
4269 		}
4270 
4271 		mode = target_psoc_get_preferred_hw_mode(tgt_hdl);
4272 		switch (mode) {
4273 		case WMI_HOST_HW_MODE_SBS_PASSIVE:
4274 		case WMI_HOST_HW_MODE_SBS:
4275 		case WMI_HOST_HW_MODE_DBS_SBS:
4276 		case WMI_HOST_HW_MODE_DBS_OR_SBS:
4277 			is_agile_scan_inprog_5g_pdev = false;
4278 			wlan_objmgr_iterate_obj_list
4279 				(psoc, WLAN_PDEV_OP,
4280 				 target_if_is_agile_scan_active_in_5g,
4281 				 &is_agile_scan_inprog_5g_pdev, 0,
4282 				 WLAN_SPECTRAL_ID);
4283 			break;
4284 		default:
4285 			is_agile_scan_inprog_5g_pdev = false;
4286 			break;
4287 		}
4288 
4289 		if (is_agile_scan_inprog_5g_pdev) {
4290 			spectral_err("Agile Scan in progress in one of the SBS 5G pdev");
4291 			*err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED;
4292 			return QDF_STATUS_E_FAILURE;
4293 		}
4294 	}
4295 
4296 	if (smode == SPECTRAL_SCAN_MODE_AGILE) {
4297 		bool is_aspectral_prohibited = false;
4298 		QDF_STATUS status;
4299 
4300 		status = wlan_objmgr_iterate_obj_list
4301 				(psoc, WLAN_PDEV_OP,
4302 				 target_if_is_aspectral_prohibited_by_adfs,
4303 				 &is_aspectral_prohibited, 0,
4304 				 WLAN_SPECTRAL_ID);
4305 		if (QDF_IS_STATUS_ERROR(status)) {
4306 			spectral_err("Failed to iterate over pdevs");
4307 			*err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED;
4308 			return QDF_STATUS_E_FAILURE;
4309 		}
4310 
4311 		if (is_aspectral_prohibited) {
4312 			*err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED;
4313 			return QDF_STATUS_E_FAILURE;
4314 		}
4315 	}
4316 
4317 	if (!spectral->params_valid[smode]) {
4318 		target_if_spectral_info_read(spectral,
4319 					     smode,
4320 					     TARGET_IF_SPECTRAL_INFO_PARAMS,
4321 					     &spectral->params[smode],
4322 					     sizeof(spectral->params[smode]));
4323 		spectral->params_valid[smode] = true;
4324 	}
4325 
4326 	qdf_spin_lock(&spectral->spectral_lock);
4327 	if (smode == SPECTRAL_SCAN_MODE_AGILE) {
4328 		QDF_STATUS status;
4329 		bool is_overlapping;
4330 		enum phy_ch_width ch_width[SPECTRAL_SCAN_MODE_MAX];
4331 		enum spectral_scan_mode m;
4332 		enum phy_ch_width op_ch_width;
4333 		enum phy_ch_width agile_ch_width;
4334 
4335 		m = SPECTRAL_SCAN_MODE_NORMAL;
4336 		for (; m < SPECTRAL_SCAN_MODE_MAX; m++)
4337 			ch_width[m] = CH_WIDTH_INVALID;
4338 		status = target_if_spectral_populate_chwidth
4339 			(spectral, ch_width, spectral->params
4340 			 [SPECTRAL_SCAN_MODE_AGILE].ss_frequency.cfreq2 > 0);
4341 		if (QDF_IS_STATUS_ERROR(status)) {
4342 			qdf_spin_unlock(&spectral->spectral_lock);
4343 			spectral_err("Failed to populate channel width");
4344 			return QDF_STATUS_E_FAILURE;
4345 		}
4346 		op_ch_width = ch_width[SPECTRAL_SCAN_MODE_NORMAL];
4347 		agile_ch_width = ch_width[SPECTRAL_SCAN_MODE_AGILE];
4348 
4349 		if (!spectral->params[smode].ss_frequency.cfreq1 ||
4350 		    (agile_ch_width == CH_WIDTH_80P80MHZ &&
4351 		    !spectral->params[smode].ss_frequency.cfreq2)) {
4352 			*err = SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED;
4353 			qdf_spin_unlock(&spectral->spectral_lock);
4354 			return QDF_STATUS_E_FAILURE;
4355 		}
4356 
4357 		status = target_if_is_agile_span_overlap_with_operating_span
4358 				(spectral, ch_width,
4359 				 &spectral->params[smode].ss_frequency,
4360 				 &is_overlapping);
4361 		if (QDF_IS_STATUS_ERROR(status)) {
4362 			qdf_spin_unlock(&spectral->spectral_lock);
4363 			return QDF_STATUS_E_FAILURE;
4364 		}
4365 
4366 		if (is_overlapping) {
4367 			*err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
4368 			qdf_spin_unlock(&spectral->spectral_lock);
4369 			return QDF_STATUS_E_FAILURE;
4370 		}
4371 	}
4372 
4373 	target_if_spectral_scan_enable_params(spectral,
4374 					      &spectral->params[smode], smode,
4375 					      err);
4376 	qdf_spin_unlock(&spectral->spectral_lock);
4377 
4378 	return QDF_STATUS_SUCCESS;
4379 }
4380 
4381 QDF_STATUS
4382 target_if_stop_spectral_scan(struct wlan_objmgr_pdev *pdev,
4383 			     const enum spectral_scan_mode smode,
4384 			     enum spectral_cp_error_code *err)
4385 {
4386 	struct target_if_spectral_ops *p_sops;
4387 	struct target_if_spectral *spectral;
4388 
4389 	if (!err) {
4390 		spectral_err("Error code argument is null");
4391 		QDF_ASSERT(0);
4392 		return QDF_STATUS_E_FAILURE;
4393 	}
4394 	*err = SPECTRAL_SCAN_ERR_INVALID;
4395 
4396 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
4397 		*err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED;
4398 		spectral_err("Invalid Spectral mode %u", smode);
4399 		return QDF_STATUS_E_FAILURE;
4400 	}
4401 
4402 	if (!pdev) {
4403 		spectral_err("pdev object is NUll ");
4404 		return QDF_STATUS_E_FAILURE;
4405 	}
4406 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
4407 	if (!spectral) {
4408 		spectral_err("Spectral LMAC object is NUll ");
4409 		return QDF_STATUS_E_FAILURE;
4410 	}
4411 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
4412 
4413 	qdf_spin_lock(&spectral->spectral_lock);
4414 	p_sops->stop_spectral_scan(spectral, smode);
4415 	if (spectral->classify_scan) {
4416 		/* TODO : Check if this logic is necessary */
4417 		spectral->detects_control_channel = 0;
4418 		spectral->detects_extension_channel = 0;
4419 		spectral->detects_above_dc = 0;
4420 		spectral->detects_below_dc = 0;
4421 		spectral->classify_scan = 0;
4422 	}
4423 
4424 	spectral->send_single_packet = 0;
4425 	spectral->sc_spectral_scan = 0;
4426 	spectral->vdev_id[smode] = WLAN_INVALID_VDEV_ID;
4427 
4428 	qdf_spin_unlock(&spectral->spectral_lock);
4429 
4430 	return QDF_STATUS_SUCCESS;
4431 }
4432 
4433 /**
4434  * target_if_is_spectral_active() - Get whether Spectral is active
4435  * @pdev: Pointer to pdev object
4436  * @smode: Spectral scan mode
4437  *
4438  * API to get whether Spectral is active
4439  *
4440  * Return: True if Spectral is active, false if Spectral is not active
4441  */
4442 bool
4443 target_if_is_spectral_active(struct wlan_objmgr_pdev *pdev,
4444 			     const enum spectral_scan_mode smode)
4445 {
4446 	struct target_if_spectral *spectral = NULL;
4447 	struct target_if_spectral_ops *p_sops = NULL;
4448 
4449 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
4450 
4451 	if (!spectral) {
4452 		spectral_err("SPECTRAL : Module doesn't exist");
4453 		return QDF_STATUS_E_FAILURE;
4454 	}
4455 
4456 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
4457 
4458 	if (!p_sops) {
4459 		spectral_err("p_sops is null");
4460 		return QDF_STATUS_E_FAILURE;
4461 	}
4462 
4463 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
4464 		spectral_err("Invalid Spectral mode %u", smode);
4465 		return QDF_STATUS_E_FAILURE;
4466 	}
4467 
4468 	return p_sops->is_spectral_active(spectral, smode);
4469 }
4470 
4471 /**
4472  * target_if_is_spectral_enabled() - Get whether Spectral is enabled
4473  * @pdev: Pointer to pdev object
4474  * @smode: Spectral scan mode
4475  *
4476  * API to get whether Spectral is enabled
4477  *
4478  * Return: True if Spectral is enabled, false if Spectral is not enabled
4479  */
4480 bool
4481 target_if_is_spectral_enabled(struct wlan_objmgr_pdev *pdev,
4482 			      enum spectral_scan_mode smode)
4483 {
4484 	struct target_if_spectral *spectral = NULL;
4485 	struct target_if_spectral_ops *p_sops = NULL;
4486 
4487 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
4488 
4489 	if (!spectral) {
4490 		spectral_err("SPECTRAL : Module doesn't exist");
4491 		return QDF_STATUS_E_FAILURE;
4492 	}
4493 
4494 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
4495 
4496 	if (!p_sops) {
4497 		spectral_err("p_sops is null");
4498 		return QDF_STATUS_E_FAILURE;
4499 	}
4500 
4501 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
4502 		spectral_err("Invalid Spectral mode %u", smode);
4503 		return QDF_STATUS_E_FAILURE;
4504 	}
4505 
4506 	return p_sops->is_spectral_enabled(spectral, smode);
4507 }
4508 
4509 #ifdef DIRECT_BUF_RX_DEBUG
4510 /**
4511  * target_if_spectral_do_dbr_ring_debug() - Start/Stop Spectral DMA ring debug
4512  * @pdev: Pointer to pdev object
4513  * @enable: Enable/Disable Spectral DMA ring debug
4514  *
4515  * Start/stop Spectral DMA ring debug based on @enable.
4516  * Also save the state for future use.
4517  *
4518  * Return: QDF_STATUS of operation
4519  */
4520 static QDF_STATUS
4521 target_if_spectral_do_dbr_ring_debug(struct wlan_objmgr_pdev *pdev, bool enable)
4522 {
4523 	struct target_if_spectral *spectral;
4524 	struct wlan_lmac_if_tx_ops *tx_ops;
4525 	struct wlan_objmgr_psoc *psoc;
4526 
4527 	if (!pdev)
4528 		return QDF_STATUS_E_FAILURE;
4529 
4530 	psoc = wlan_pdev_get_psoc(pdev);
4531 	if (!psoc) {
4532 		spectral_err("psoc is null");
4533 		return QDF_STATUS_E_INVAL;
4534 	}
4535 
4536 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
4537 	if (!tx_ops) {
4538 		spectral_err("tx_ops is NULL");
4539 		return QDF_STATUS_E_INVAL;
4540 	}
4541 
4542 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
4543 	if (!spectral) {
4544 		spectral_err("Spectal LMAC object is NULL");
4545 		return QDF_STATUS_E_INVAL;
4546 	}
4547 
4548 	/* Save the state */
4549 	spectral->dbr_ring_debug = enable;
4550 
4551 	if (enable)
4552 		return tx_ops->dbr_tx_ops.direct_buf_rx_start_ring_debug(
4553 				pdev, 0, SPECTRAL_DBR_RING_DEBUG_SIZE);
4554 	else
4555 		return tx_ops->dbr_tx_ops.direct_buf_rx_stop_ring_debug(
4556 				pdev, 0);
4557 
4558 	return QDF_STATUS_SUCCESS;
4559 }
4560 
4561 /**
4562  * target_if_spectral_do_dbr_buff_debug() - Start/Stop Spectral DMA buffer debug
4563  * @pdev: Pointer to pdev object
4564  * @enable: Enable/Disable Spectral DMA buffer debug
4565  *
4566  * Start/stop Spectral DMA buffer debug based on @enable.
4567  * Also save the state for future use.
4568  *
4569  * Return: QDF_STATUS of operation
4570  */
4571 static QDF_STATUS
4572 target_if_spectral_do_dbr_buff_debug(struct wlan_objmgr_pdev *pdev, bool enable)
4573 {
4574 	struct target_if_spectral *spectral;
4575 	struct wlan_lmac_if_tx_ops *tx_ops;
4576 	struct wlan_objmgr_psoc *psoc;
4577 
4578 	if (!pdev)
4579 		return QDF_STATUS_E_FAILURE;
4580 
4581 	psoc = wlan_pdev_get_psoc(pdev);
4582 	if (!psoc) {
4583 		spectral_err("psoc is null");
4584 		return QDF_STATUS_E_INVAL;
4585 	}
4586 
4587 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
4588 	if (!tx_ops) {
4589 		spectral_err("tx_ops is NULL");
4590 		return QDF_STATUS_E_INVAL;
4591 	}
4592 
4593 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
4594 	if (!spectral) {
4595 		spectral_err("Spectal LMAC object is NULL");
4596 		return QDF_STATUS_E_INVAL;
4597 	}
4598 
4599 	/* Save the state */
4600 	spectral->dbr_buff_debug = enable;
4601 
4602 	if (enable)
4603 		return tx_ops->dbr_tx_ops.direct_buf_rx_start_buffer_poisoning(
4604 				pdev, 0, MEM_POISON_SIGNATURE);
4605 	else
4606 		return tx_ops->dbr_tx_ops.direct_buf_rx_stop_buffer_poisoning(
4607 				pdev, 0);
4608 }
4609 
4610 /**
4611  * target_if_spectral_check_and_do_dbr_buff_debug() - Start/Stop Spectral buffer
4612  * debug based on the previous state
4613  * @pdev: Pointer to pdev object
4614  *
4615  * Return: QDF_STATUS of operation
4616  */
4617 static QDF_STATUS
4618 target_if_spectral_check_and_do_dbr_buff_debug(struct wlan_objmgr_pdev *pdev)
4619 {
4620 	struct target_if_spectral *spectral;
4621 
4622 	if (!pdev) {
4623 		spectral_err("pdev is NULL!");
4624 		return QDF_STATUS_E_FAILURE;
4625 	}
4626 
4627 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
4628 	if (!spectral) {
4629 		spectral_err("Spectal LMAC object is NULL");
4630 		return QDF_STATUS_E_INVAL;
4631 	}
4632 
4633 	if (spectral->dbr_buff_debug)
4634 		return target_if_spectral_do_dbr_buff_debug(pdev, true);
4635 	else
4636 		return target_if_spectral_do_dbr_buff_debug(pdev, false);
4637 }
4638 
4639 /**
4640  * target_if_spectral_check_and_do_dbr_ring_debug() - Start/Stop Spectral ring
4641  * debug based on the previous state
4642  * @pdev: Pointer to pdev object
4643  *
4644  * Return: QDF_STATUS of operation
4645  */
4646 static QDF_STATUS
4647 target_if_spectral_check_and_do_dbr_ring_debug(struct wlan_objmgr_pdev *pdev)
4648 {
4649 	struct target_if_spectral *spectral;
4650 
4651 	if (!pdev) {
4652 		spectral_err("pdev is NULL!");
4653 		return QDF_STATUS_E_FAILURE;
4654 	}
4655 
4656 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
4657 	if (!spectral) {
4658 		spectral_err("Spectal LMAC object is NULL");
4659 		return QDF_STATUS_E_INVAL;
4660 	}
4661 
4662 	if (spectral->dbr_ring_debug)
4663 		return target_if_spectral_do_dbr_ring_debug(pdev, true);
4664 	else
4665 		return target_if_spectral_do_dbr_ring_debug(pdev, false);
4666 }
4667 
4668 /**
4669  * target_if_spectral_set_dma_debug() - Set DMA debug for Spectral
4670  * @pdev: Pointer to pdev object
4671  * @dma_debug_type: Type of Spectral DMA debug i.e., ring or buffer debug
4672  * @debug_value: Value to be set for @dma_debug_type
4673  *
4674  * Set DMA debug for Spectral and start/stop Spectral DMA debug function
4675  * based on @debug_value
4676  *
4677  * Return: QDF_STATUS of operation
4678  */
4679 static QDF_STATUS
4680 target_if_spectral_set_dma_debug(
4681 	struct wlan_objmgr_pdev *pdev,
4682 	enum spectral_dma_debug dma_debug_type,
4683 	bool debug_value)
4684 {
4685 	struct target_if_spectral_ops *p_sops;
4686 	struct wlan_objmgr_psoc *psoc;
4687 	struct wlan_lmac_if_tx_ops *tx_ops;
4688 	struct target_if_spectral *spectral;
4689 
4690 	if (!pdev)
4691 		return QDF_STATUS_E_FAILURE;
4692 
4693 	psoc = wlan_pdev_get_psoc(pdev);
4694 	if (!psoc) {
4695 		spectral_err("psoc is null");
4696 		return QDF_STATUS_E_INVAL;
4697 	}
4698 
4699 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
4700 	if (!tx_ops) {
4701 		spectral_err("tx_ops is NULL");
4702 		return QDF_STATUS_E_FAILURE;
4703 	}
4704 
4705 	if (!tx_ops->target_tx_ops.tgt_get_tgt_type) {
4706 		spectral_err("Unable to fetch target type");
4707 		return QDF_STATUS_E_FAILURE;
4708 	}
4709 
4710 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
4711 	if (!spectral) {
4712 		spectral_err("Spectal LMAC object is NULL");
4713 		return QDF_STATUS_E_INVAL;
4714 	}
4715 
4716 	if (spectral->direct_dma_support) {
4717 		p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
4718 		if (p_sops->is_spectral_active(spectral,
4719 					       SPECTRAL_SCAN_MODE_NORMAL) ||
4720 		    p_sops->is_spectral_active(spectral,
4721 					       SPECTRAL_SCAN_MODE_AGILE)) {
4722 			spectral_err("Altering DBR debug config isn't allowed during an ongoing scan");
4723 			return QDF_STATUS_E_FAILURE;
4724 		}
4725 
4726 		switch (dma_debug_type) {
4727 		case SPECTRAL_DMA_RING_DEBUG:
4728 			target_if_spectral_do_dbr_ring_debug(pdev, debug_value);
4729 			break;
4730 
4731 		case SPECTRAL_DMA_BUFFER_DEBUG:
4732 			target_if_spectral_do_dbr_buff_debug(pdev, debug_value);
4733 			break;
4734 
4735 		default:
4736 			spectral_err("Unsupported DMA debug type : %d",
4737 				     dma_debug_type);
4738 			return QDF_STATUS_E_FAILURE;
4739 		}
4740 	}
4741 	return QDF_STATUS_SUCCESS;
4742 }
4743 #endif /* DIRECT_BUF_RX_DEBUG */
4744 
4745 /**
4746  * target_if_spectral_direct_dma_support() - Get Direct-DMA support
4747  * @pdev: Pointer to pdev object
4748  *
4749  * Return: Whether Direct-DMA is supported on this radio
4750  */
4751 static bool
4752 target_if_spectral_direct_dma_support(struct wlan_objmgr_pdev *pdev)
4753 {
4754 	struct target_if_spectral *spectral;
4755 
4756 	if (!pdev) {
4757 		spectral_err("pdev is NULL!");
4758 		return false;
4759 	}
4760 
4761 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
4762 	if (!spectral) {
4763 		spectral_err("Spectral LMAC object is NULL");
4764 		return false;
4765 	}
4766 
4767 	return spectral->direct_dma_support;
4768 }
4769 
4770 /**
4771  * target_if_set_debug_level() - Set debug level for Spectral
4772  * @pdev: Pointer to pdev object
4773  * @debug_level: Debug level
4774  *
4775  * API to set the debug level for Spectral
4776  *
4777  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
4778  */
4779 QDF_STATUS
4780 target_if_set_debug_level(struct wlan_objmgr_pdev *pdev, uint32_t debug_level)
4781 {
4782 	spectral_debug_level = (DEBUG_SPECTRAL << debug_level);
4783 
4784 	return QDF_STATUS_SUCCESS;
4785 }
4786 
4787 /**
4788  * target_if_get_debug_level() - Get debug level for Spectral
4789  * @pdev: Pointer to pdev object
4790  *
4791  * API to get the debug level for Spectral
4792  *
4793  * Return: Current debug level
4794  */
4795 uint32_t
4796 target_if_get_debug_level(struct wlan_objmgr_pdev *pdev)
4797 {
4798 	return spectral_debug_level;
4799 }
4800 
4801 /**
4802  * target_if_get_spectral_capinfo() - Get Spectral capability information
4803  * @pdev: Pointer to pdev object
4804  * @scaps: Buffer into which data should be copied
4805  *
4806  * API to get the spectral capability information
4807  *
4808  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
4809  */
4810 QDF_STATUS
4811 target_if_get_spectral_capinfo(struct wlan_objmgr_pdev *pdev,
4812 			       struct spectral_caps *scaps)
4813 {
4814 	struct target_if_spectral *spectral = NULL;
4815 
4816 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
4817 	if (!spectral) {
4818 		spectral_err("SPECTRAL : Module doesn't exist");
4819 		return QDF_STATUS_E_FAILURE;
4820 	}
4821 
4822 	qdf_mem_copy(scaps, &spectral->capability,
4823 		     sizeof(struct spectral_caps));
4824 
4825 	return QDF_STATUS_SUCCESS;
4826 }
4827 
4828 /**
4829  * target_if_get_spectral_diagstats() - Get Spectral diagnostic statistics
4830  * @pdev:  Pointer to pdev object
4831  * @stats: Buffer into which data should be copied
4832  *
4833  * API to get the spectral diagnostic statistics
4834  *
4835  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
4836  */
4837 QDF_STATUS
4838 target_if_get_spectral_diagstats(struct wlan_objmgr_pdev *pdev,
4839 				 struct spectral_diag_stats *stats)
4840 {
4841 	struct target_if_spectral *spectral = NULL;
4842 
4843 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
4844 	if (!spectral) {
4845 		spectral_err("SPECTRAL : Module doesn't exist");
4846 		return QDF_STATUS_E_FAILURE;
4847 	}
4848 
4849 	qdf_mem_copy(stats, &spectral->diag_stats,
4850 		     sizeof(struct spectral_diag_stats));
4851 
4852 	return QDF_STATUS_SUCCESS;
4853 }
4854 
4855 /**
4856  * target_if_register_spectral_wmi_ops() - Register Spectral WMI operations
4857  * @psoc: Pointer to psoc object
4858  * @wmi_ops: Pointer to the structure having Spectral WMI operations
4859  *
4860  * API for registering Spectral WMI operations in
4861  * spectral internal data structure
4862  *
4863  * Return: QDF_STATUS
4864  */
4865 static QDF_STATUS
4866 target_if_register_spectral_wmi_ops(struct wlan_objmgr_psoc *psoc,
4867 				    struct spectral_wmi_ops *wmi_ops)
4868 {
4869 	struct target_if_psoc_spectral *psoc_spectral;
4870 
4871 	psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
4872 	if (!psoc_spectral) {
4873 		spectral_err("Spectral LMAC object is null");
4874 		return QDF_STATUS_E_INVAL;
4875 	}
4876 
4877 	psoc_spectral->wmi_ops = *wmi_ops;
4878 
4879 	return QDF_STATUS_SUCCESS;
4880 }
4881 
4882 /**
4883  * target_if_register_spectral_tgt_ops() - Register Spectral target operations
4884  * @psoc: Pointer to psoc object
4885  * @tgt_ops: Pointer to the structure having Spectral target operations
4886  *
4887  * API for registering Spectral target operations in
4888  * spectral internal data structure
4889  *
4890  * Return: QDF_STATUS
4891  */
4892 static QDF_STATUS
4893 target_if_register_spectral_tgt_ops(struct wlan_objmgr_psoc *psoc,
4894 				    struct spectral_tgt_ops *tgt_ops)
4895 {
4896 	if (!psoc) {
4897 		spectral_err("psoc is null");
4898 		return QDF_STATUS_E_INVAL;
4899 	}
4900 
4901 	ops_tgt = *tgt_ops;
4902 
4903 	return QDF_STATUS_SUCCESS;
4904 }
4905 
4906 /**
4907  * target_if_register_netlink_cb() - Register Netlink callbacks
4908  * @pdev: Pointer to pdev object
4909  * @nl_cb: Netlink callbacks to register
4910  *
4911  * Return: void
4912  */
4913 static void
4914 target_if_register_netlink_cb(
4915 	struct wlan_objmgr_pdev *pdev,
4916 	struct spectral_nl_cb *nl_cb)
4917 {
4918 	struct target_if_spectral *spectral = NULL;
4919 
4920 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
4921 
4922 	if (!spectral) {
4923 		spectral_err("SPECTRAL : Module doesn't exist");
4924 		return;
4925 	}
4926 
4927 	qdf_mem_copy(&spectral->nl_cb, nl_cb, sizeof(struct spectral_nl_cb));
4928 
4929 	if (spectral->use_nl_bcast)
4930 		spectral->send_phy_data = spectral->nl_cb.send_nl_bcast;
4931 	else
4932 		spectral->send_phy_data = spectral->nl_cb.send_nl_unicast;
4933 }
4934 
4935 /**
4936  * target_if_use_nl_bcast() - Get whether to use broadcast/unicast while sending
4937  * Netlink messages to the application layer
4938  * @pdev: Pointer to pdev object
4939  *
4940  * Return: true for broadcast, false for unicast
4941  */
4942 static bool
4943 target_if_use_nl_bcast(struct wlan_objmgr_pdev *pdev)
4944 {
4945 	struct target_if_spectral *spectral = NULL;
4946 
4947 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
4948 
4949 	if (!spectral) {
4950 		spectral_err("SPECTRAL : Module doesn't exist");
4951 		return false;
4952 	}
4953 
4954 	return spectral->use_nl_bcast;
4955 }
4956 
4957 /**
4958  * target_if_deregister_netlink_cb() - De-register Netlink callbacks
4959  * @pdev: Pointer to pdev object
4960  *
4961  * Return: void
4962  */
4963 static void
4964 target_if_deregister_netlink_cb(struct wlan_objmgr_pdev *pdev)
4965 {
4966 	struct target_if_spectral *spectral = NULL;
4967 
4968 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
4969 	if (!spectral) {
4970 		spectral_err("SPECTRAL : Module doesn't exist");
4971 		return;
4972 	}
4973 
4974 	qdf_mem_zero(&spectral->nl_cb, sizeof(struct spectral_nl_cb));
4975 }
4976 
4977 static int
4978 target_if_process_spectral_report(struct wlan_objmgr_pdev *pdev,
4979 				  void *payload)
4980 {
4981 	struct target_if_spectral *spectral = NULL;
4982 	struct target_if_spectral_ops *p_sops = NULL;
4983 
4984 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
4985 	if (!spectral) {
4986 		spectral_err("SPECTRAL : Module doesn't exist");
4987 		return -EPERM;
4988 	}
4989 
4990 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
4991 
4992 	if (!p_sops) {
4993 		spectral_err("p_sops is null");
4994 		return -EPERM;
4995 	}
4996 
4997 	return p_sops->process_spectral_report(pdev, payload);
4998 }
4999 
5000 #ifdef DIRECT_BUF_RX_DEBUG
5001 static inline void
5002 target_if_sptrl_debug_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
5003 {
5004 	if (!tx_ops) {
5005 		spectral_err("tx_ops is NULL");
5006 		return;
5007 	}
5008 
5009 	tx_ops->sptrl_tx_ops.sptrlto_set_dma_debug =
5010 		target_if_spectral_set_dma_debug;
5011 	tx_ops->sptrl_tx_ops.sptrlto_check_and_do_dbr_ring_debug =
5012 		target_if_spectral_check_and_do_dbr_ring_debug;
5013 	tx_ops->sptrl_tx_ops.sptrlto_check_and_do_dbr_buff_debug =
5014 		target_if_spectral_check_and_do_dbr_buff_debug;
5015 }
5016 #else
5017 static inline void
5018 target_if_sptrl_debug_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
5019 {
5020 }
5021 #endif
5022 
5023 #if defined(WLAN_CONV_SPECTRAL_ENABLE) && defined(SPECTRAL_MODULIZED_ENABLE)
5024 /**
5025  * target_if_spectral_wmi_unified_register_event_handler() - Wrapper function to
5026  * register WMI event handler
5027  * @psoc: Pointer to psoc object
5028  * @event_id: Event id
5029  * @handler_func: Handler function
5030  * @rx_ctx: Context of WMI event processing
5031  *
5032  * Wrapper function to register WMI event handler
5033  *
5034  * Return: 0 for success else failure
5035  */
5036 static int
5037 target_if_spectral_wmi_unified_register_event_handler(
5038 				struct wlan_objmgr_psoc *psoc,
5039 				wmi_conv_event_id event_id,
5040 				wmi_unified_event_handler handler_func,
5041 				uint8_t rx_ctx)
5042 {
5043 	wmi_unified_t wmi_handle;
5044 	struct target_if_psoc_spectral *psoc_spectral;
5045 
5046 	if (!psoc) {
5047 		spectral_err("psoc is null");
5048 		return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
5049 	}
5050 
5051 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
5052 	if (!wmi_handle) {
5053 		spectral_err("WMI handle is null");
5054 		return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
5055 	}
5056 
5057 	psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
5058 	if (!psoc_spectral) {
5059 		spectral_err("spectral object is null");
5060 		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
5061 	}
5062 
5063 	return psoc_spectral->wmi_ops.wmi_unified_register_event_handler(
5064 			wmi_handle, event_id, handler_func, rx_ctx);
5065 }
5066 
5067 /**
5068  * target_if_spectral_wmi_unified_unregister_event_handler() - Wrapper function
5069  * to unregister WMI event handler
5070  * @psoc: Pointer to psoc object
5071  * @event_id: Event id
5072  *
5073  * Wrapper function to unregister WMI event handler
5074  *
5075  * Return: 0 for success else failure
5076  */
5077 static int
5078 target_if_spectral_wmi_unified_unregister_event_handler(
5079 				struct wlan_objmgr_psoc *psoc,
5080 				wmi_conv_event_id event_id)
5081 {
5082 	wmi_unified_t wmi_handle;
5083 	struct target_if_psoc_spectral *psoc_spectral;
5084 
5085 	if (!psoc) {
5086 		spectral_err("psoc is null");
5087 		return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
5088 	}
5089 
5090 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
5091 	if (!wmi_handle) {
5092 		spectral_err("WMI handle is null");
5093 		return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
5094 	}
5095 
5096 	psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
5097 	if (!psoc_spectral) {
5098 		spectral_err("spectral object is null");
5099 		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
5100 	}
5101 
5102 	return psoc_spectral->wmi_ops.wmi_unified_unregister_event_handler(
5103 					wmi_handle, event_id);
5104 }
5105 
5106 /**
5107  * target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param() - Wrapper
5108  * function to extract fixed parameters from start scan response event
5109  * @psoc: Pointer to psoc object
5110  * @evt_buf: Event buffer
5111  * @param: Start scan response parameters
5112  *
5113  * Wrapper function to extract fixed parameters from start scan response event
5114  *
5115  * Return: QDF_STATUS
5116  */
5117 static QDF_STATUS
5118 target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param(
5119 			struct wlan_objmgr_psoc *psoc,
5120 			uint8_t *evt_buf,
5121 			struct spectral_startscan_resp_params *param)
5122 {
5123 	wmi_unified_t wmi_handle;
5124 	struct target_if_psoc_spectral *psoc_spectral;
5125 
5126 	if (!psoc) {
5127 		spectral_err("psoc is null");
5128 		return QDF_STATUS_E_INVAL;
5129 	}
5130 
5131 	if (!evt_buf) {
5132 		spectral_err("WMI event buffer is null");
5133 		return QDF_STATUS_E_INVAL;
5134 	}
5135 
5136 	if (!param) {
5137 		spectral_err("Spectral startscan response parameters is null");
5138 		return QDF_STATUS_E_INVAL;
5139 	}
5140 
5141 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
5142 	if (!wmi_handle) {
5143 		spectral_err("WMI handle is null");
5144 		return QDF_STATUS_E_INVAL;
5145 	}
5146 
5147 	psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
5148 	if (!psoc_spectral) {
5149 		spectral_err("spectral object is null");
5150 		return QDF_STATUS_E_FAILURE;
5151 	}
5152 
5153 	return psoc_spectral->wmi_ops.wmi_extract_pdev_sscan_fw_cmd_fixed_param(
5154 			wmi_handle, evt_buf, param);
5155 }
5156 
5157 /**
5158  * target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index() - Wrapper
5159  * function to extract start and end indices of primary 80 MHz, 5 MHz and
5160  * secondary 80 MHz FFT bins
5161  * @psoc: Pointer to psoc object
5162  * @evt_buf: Event buffer
5163  * @param: FFT bin start and end indices
5164  *
5165  * Wrapper function to extract start and end indices of primary 80 MHz, 5 MHz
5166  * and secondary 80 MHz FFT bins
5167  *
5168  * Return: QDF_STATUS
5169  */
5170 static QDF_STATUS
5171 target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index(
5172 			struct wlan_objmgr_psoc *psoc,
5173 			uint8_t *evt_buf,
5174 			struct spectral_fft_bin_markers_160_165mhz *param)
5175 {
5176 	wmi_unified_t wmi_handle;
5177 	struct target_if_psoc_spectral *psoc_spectral;
5178 
5179 	if (!psoc) {
5180 		spectral_err("psoc is null");
5181 		return QDF_STATUS_E_INVAL;
5182 	}
5183 
5184 	if (!evt_buf) {
5185 		spectral_err("WMI event buffer is null");
5186 		return QDF_STATUS_E_INVAL;
5187 	}
5188 
5189 	if (!param) {
5190 		spectral_err("Spectral FFT bin markers is null");
5191 		return QDF_STATUS_E_INVAL;
5192 	}
5193 
5194 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
5195 	if (!wmi_handle) {
5196 		spectral_err("WMI handle is null");
5197 		return QDF_STATUS_E_INVAL;
5198 	}
5199 
5200 	psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
5201 	if (!psoc_spectral) {
5202 		spectral_err("spectral object is null");
5203 		return QDF_STATUS_E_FAILURE;
5204 	}
5205 
5206 	return psoc_spectral->wmi_ops.wmi_extract_pdev_sscan_fft_bin_index(
5207 			wmi_handle, evt_buf, param);
5208 }
5209 
5210 /**
5211  * target_if_spectral_get_psoc_from_scn_handle() - Wrapper function to get psoc
5212  * object from scn handle
5213  * @scn: scn handle
5214  *
5215  * Wrapper function to get psoc object from scn handle
5216  *
5217  * Return: Pointer to psoc object
5218  */
5219 static struct wlan_objmgr_psoc *
5220 target_if_spectral_get_psoc_from_scn_handle(ol_scn_t scn)
5221 {
5222 	if (!scn) {
5223 		spectral_err("scn is null");
5224 		return NULL;
5225 	}
5226 
5227 	return ops_tgt.tgt_get_psoc_from_scn_hdl(scn);
5228 }
5229 #else
5230 /**
5231  * target_if_spectral_wmi_unified_register_event_handler() - Wrapper function to
5232  * register WMI event handler
5233  * @psoc: Pointer to psoc object
5234  * @event_id: Event id
5235  * @handler_func: Handler function
5236  * @rx_ctx: Context of WMI event processing
5237  *
5238  * Wrapper function to register WMI event handler
5239  *
5240  * Return: 0 for success else failure
5241  */
5242 static int
5243 target_if_spectral_wmi_unified_register_event_handler(
5244 				struct wlan_objmgr_psoc *psoc,
5245 				wmi_conv_event_id event_id,
5246 				wmi_unified_event_handler handler_func,
5247 				uint8_t rx_ctx)
5248 {
5249 	wmi_unified_t wmi_handle;
5250 
5251 	if (!psoc) {
5252 		spectral_err("psoc is null");
5253 		return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
5254 	}
5255 
5256 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
5257 	if (!wmi_handle) {
5258 		spectral_err("WMI handle is null");
5259 		return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
5260 	}
5261 
5262 	return wmi_unified_register_event_handler(wmi_handle, event_id,
5263 						  handler_func, rx_ctx);
5264 }
5265 
5266 /**
5267  * target_if_spectral_wmi_unified_unregister_event_handler() - Wrapper function
5268  * to unregister WMI event handler
5269  * @psoc: Pointer to psoc object
5270  * @event_id: Event id
5271  *
5272  * Wrapper function to unregister WMI event handler
5273  *
5274  * Return: 0 for success else failure
5275  */
5276 static int
5277 target_if_spectral_wmi_unified_unregister_event_handler(
5278 				struct wlan_objmgr_psoc *psoc,
5279 				wmi_conv_event_id event_id)
5280 {
5281 	wmi_unified_t wmi_handle;
5282 
5283 	if (!psoc) {
5284 		spectral_err("psoc is null");
5285 		return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
5286 	}
5287 
5288 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
5289 	if (!wmi_handle) {
5290 		spectral_err("WMI handle is null");
5291 		return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
5292 	}
5293 
5294 	return wmi_unified_unregister_event_handler(wmi_handle, event_id);
5295 }
5296 
5297 /**
5298  * target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param() - Wrapper
5299  * function to extract fixed parameters from start scan response event
5300  * @psoc: Pointer to psoc object
5301  * @evt_buf: Event buffer
5302  * @param: Start scan response parameters
5303  *
5304  * Wrapper function to extract fixed parameters from start scan response event
5305  *
5306  * Return: QDF_STATUS
5307  */
5308 static QDF_STATUS
5309 target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param(
5310 			struct wlan_objmgr_psoc *psoc,
5311 			uint8_t *evt_buf,
5312 			struct spectral_startscan_resp_params *param)
5313 {
5314 	wmi_unified_t wmi_handle;
5315 
5316 	if (!psoc) {
5317 		spectral_err("psoc is null");
5318 		return QDF_STATUS_E_INVAL;
5319 	}
5320 
5321 	if (!evt_buf) {
5322 		spectral_err("WMI event buffer is null");
5323 		return QDF_STATUS_E_INVAL;
5324 	}
5325 
5326 	if (!param) {
5327 		spectral_err("Spectral startscan response parameters is null");
5328 		return QDF_STATUS_E_INVAL;
5329 	}
5330 
5331 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
5332 	if (!wmi_handle) {
5333 		spectral_err("WMI handle is null");
5334 		return QDF_STATUS_E_INVAL;
5335 	}
5336 
5337 	return wmi_extract_pdev_sscan_fw_cmd_fixed_param(wmi_handle, evt_buf,
5338 							 param);
5339 }
5340 
5341 /**
5342  * target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index() - Wrapper
5343  * function to extract start and end indices of primary 80 MHz, 5 MHz and
5344  * secondary 80 MHz FFT bins
5345  * @psoc: Pointer to psoc object
5346  * @evt_buf: Event buffer
5347  * @param: FFT bin start and end indices
5348  *
5349  * Wrapper function to extract start and end indices of primary 80 MHz, 5 MHz
5350  * and secondary 80 MHz FFT bins
5351  *
5352  * Return: QDF_STATUS
5353  */
5354 static QDF_STATUS
5355 target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index(
5356 			struct wlan_objmgr_psoc *psoc,
5357 			uint8_t *evt_buf,
5358 			struct spectral_fft_bin_markers_160_165mhz *param)
5359 {
5360 	wmi_unified_t wmi_handle;
5361 
5362 	if (!psoc) {
5363 		spectral_err("psoc is null");
5364 		return QDF_STATUS_E_INVAL;
5365 	}
5366 
5367 	if (!evt_buf) {
5368 		spectral_err("WMI event buffer is null");
5369 		return QDF_STATUS_E_INVAL;
5370 	}
5371 
5372 	if (!param) {
5373 		spectral_err("Spectral FFT bin markers is null");
5374 		return QDF_STATUS_E_INVAL;
5375 	}
5376 
5377 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
5378 	if (!wmi_handle) {
5379 		spectral_err("WMI handle is null");
5380 		return QDF_STATUS_E_INVAL;
5381 	}
5382 
5383 	return wmi_extract_pdev_sscan_fft_bin_index(wmi_handle, evt_buf, param);
5384 }
5385 
5386 /**
5387  * target_if_spectral_get_psoc_from_scn_handle() - Wrapper function to get psoc
5388  * object from scn handle
5389  * @scn: scn handle
5390  *
5391  * Wrapper function to get psoc object from scn handle
5392  *
5393  * Return: Pointer to psoc object
5394  */
5395 static struct wlan_objmgr_psoc *
5396 target_if_spectral_get_psoc_from_scn_handle(ol_scn_t scn)
5397 {
5398 	if (!scn) {
5399 		spectral_err("scn is null");
5400 		return NULL;
5401 	}
5402 
5403 	return target_if_get_psoc_from_scn_hdl(scn);
5404 }
5405 #endif
5406 
5407 /**
5408  * target_if_spectral_fw_param_event_handler() - WMI event handler to
5409  * process start scan response event
5410  * @scn: Pointer to scn object
5411  * @data_buf: Pointer to event buffer
5412  * @data_len: Length of event buffer
5413  *
5414  * Return: 0 for success, else failure
5415  */
5416 static int
5417 target_if_spectral_fw_param_event_handler(ol_scn_t scn, uint8_t *data_buf,
5418 					  uint32_t data_len)
5419 {
5420 	QDF_STATUS status;
5421 	struct wlan_objmgr_psoc *psoc;
5422 	struct wlan_objmgr_pdev *pdev;
5423 	struct wmi_unified *wmi_handle;
5424 	struct spectral_startscan_resp_params event_params = {0};
5425 	struct target_if_psoc_spectral *psoc_spectral;
5426 	struct target_if_spectral *spectral;
5427 
5428 	if (!scn) {
5429 		spectral_err("scn handle is null");
5430 		return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
5431 	}
5432 
5433 	if (!data_buf) {
5434 		spectral_err("WMI event buffer null");
5435 		return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
5436 	}
5437 
5438 	psoc = target_if_spectral_get_psoc_from_scn_handle(scn);
5439 	if (!psoc) {
5440 		spectral_err("psoc is null");
5441 		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
5442 	}
5443 
5444 	psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
5445 	if (!psoc_spectral) {
5446 		spectral_err("spectral object is null");
5447 		return QDF_STATUS_E_FAILURE;
5448 	}
5449 
5450 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
5451 	if (!wmi_handle) {
5452 		spectral_err("WMI handle is null");
5453 		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
5454 	}
5455 
5456 	status = target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param(
5457 				psoc, data_buf, &event_params);
5458 	if (QDF_IS_STATUS_ERROR(status)) {
5459 		spectral_err("unable to extract sscan fw fixed params");
5460 		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
5461 	}
5462 
5463 	pdev = wlan_objmgr_get_pdev_by_id(psoc, event_params.pdev_id,
5464 					  WLAN_SPECTRAL_ID);
5465 	if (!pdev) {
5466 		spectral_err("pdev is null");
5467 		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
5468 	}
5469 
5470 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
5471 	if (!spectral) {
5472 		spectral_err("spectral object is null");
5473 		wlan_objmgr_pdev_release_ref(pdev, WLAN_SPECTRAL_ID);
5474 		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
5475 	}
5476 
5477 	if (event_params.num_fft_bin_index == 1) {
5478 		status =
5479 			target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index(
5480 				psoc, data_buf,
5481 				&spectral->rparams.marker[event_params.smode]);
5482 		if (QDF_IS_STATUS_ERROR(status)) {
5483 			spectral_err("unable to extract sscan fw fixed params");
5484 			wlan_objmgr_pdev_release_ref(pdev, WLAN_SPECTRAL_ID);
5485 			return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
5486 		}
5487 	} else {
5488 		spectral->rparams.marker[event_params.smode].is_valid = false;
5489 	}
5490 
5491 	wlan_objmgr_pdev_release_ref(pdev, WLAN_SPECTRAL_ID);
5492 
5493 	return qdf_status_to_os_return(QDF_STATUS_SUCCESS);
5494 }
5495 
5496 static QDF_STATUS
5497 target_if_spectral_register_events(struct wlan_objmgr_psoc *psoc)
5498 {
5499 	int ret;
5500 
5501 	if (!psoc) {
5502 		spectral_err("psoc is null");
5503 		return QDF_STATUS_E_INVAL;
5504 	}
5505 
5506 	ret = target_if_spectral_wmi_unified_register_event_handler(
5507 			psoc,
5508 			wmi_pdev_sscan_fw_param_eventid,
5509 			target_if_spectral_fw_param_event_handler,
5510 			WMI_RX_UMAC_CTX);
5511 
5512 	if (ret)
5513 		spectral_debug("event handler not supported, ret=%d", ret);
5514 
5515 	return QDF_STATUS_SUCCESS;
5516 }
5517 
5518 static QDF_STATUS
5519 target_if_spectral_unregister_events(struct wlan_objmgr_psoc *psoc)
5520 {
5521 	int ret;
5522 
5523 	if (!psoc) {
5524 		spectral_err("psoc is null");
5525 		return QDF_STATUS_E_INVAL;
5526 	}
5527 
5528 	ret = target_if_spectral_wmi_unified_unregister_event_handler(
5529 			psoc, wmi_pdev_sscan_fw_param_eventid);
5530 
5531 	if (ret)
5532 		spectral_debug("Unregister WMI event handler failed, ret = %d",
5533 			       ret);
5534 
5535 	return QDF_STATUS_SUCCESS;
5536 }
5537 
5538 void
5539 target_if_sptrl_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
5540 {
5541 	tx_ops->sptrl_tx_ops.sptrlto_pdev_spectral_init =
5542 	    target_if_pdev_spectral_init;
5543 	tx_ops->sptrl_tx_ops.sptrlto_pdev_spectral_deinit =
5544 	    target_if_pdev_spectral_deinit;
5545 	tx_ops->sptrl_tx_ops.sptrlto_psoc_spectral_init =
5546 	    target_if_psoc_spectral_init;
5547 	tx_ops->sptrl_tx_ops.sptrlto_psoc_spectral_deinit =
5548 	    target_if_psoc_spectral_deinit;
5549 	tx_ops->sptrl_tx_ops.sptrlto_set_spectral_config =
5550 	    target_if_set_spectral_config;
5551 	tx_ops->sptrl_tx_ops.sptrlto_get_spectral_config =
5552 	    target_if_get_spectral_config;
5553 	tx_ops->sptrl_tx_ops.sptrlto_start_spectral_scan =
5554 	    target_if_start_spectral_scan;
5555 	tx_ops->sptrl_tx_ops.sptrlto_stop_spectral_scan =
5556 	    target_if_stop_spectral_scan;
5557 	tx_ops->sptrl_tx_ops.sptrlto_is_spectral_active =
5558 	    target_if_is_spectral_active;
5559 	tx_ops->sptrl_tx_ops.sptrlto_is_spectral_enabled =
5560 	    target_if_is_spectral_enabled;
5561 	tx_ops->sptrl_tx_ops.sptrlto_set_debug_level =
5562 	    target_if_set_debug_level;
5563 	tx_ops->sptrl_tx_ops.sptrlto_get_debug_level =
5564 	    target_if_get_debug_level;
5565 	tx_ops->sptrl_tx_ops.sptrlto_get_spectral_capinfo =
5566 	    target_if_get_spectral_capinfo;
5567 	tx_ops->sptrl_tx_ops.sptrlto_get_spectral_diagstats =
5568 	    target_if_get_spectral_diagstats;
5569 	tx_ops->sptrl_tx_ops.sptrlto_register_spectral_wmi_ops =
5570 	    target_if_register_spectral_wmi_ops;
5571 	tx_ops->sptrl_tx_ops.sptrlto_register_spectral_tgt_ops =
5572 	    target_if_register_spectral_tgt_ops;
5573 	tx_ops->sptrl_tx_ops.sptrlto_register_netlink_cb =
5574 	    target_if_register_netlink_cb;
5575 	tx_ops->sptrl_tx_ops.sptrlto_use_nl_bcast =
5576 	    target_if_use_nl_bcast;
5577 	tx_ops->sptrl_tx_ops.sptrlto_deregister_netlink_cb =
5578 	    target_if_deregister_netlink_cb;
5579 	tx_ops->sptrl_tx_ops.sptrlto_process_spectral_report =
5580 	    target_if_process_spectral_report;
5581 	tx_ops->sptrl_tx_ops.sptrlto_direct_dma_support =
5582 		target_if_spectral_direct_dma_support;
5583 	tx_ops->sptrl_tx_ops.sptrlto_register_events =
5584 		target_if_spectral_register_events;
5585 	tx_ops->sptrl_tx_ops.sptrlto_unregister_events =
5586 		target_if_spectral_unregister_events;
5587 
5588 	target_if_sptrl_debug_register_tx_ops(tx_ops);
5589 }
5590 qdf_export_symbol(target_if_sptrl_register_tx_ops);
5591 
5592 void
5593 target_if_spectral_send_intf_found_msg(struct wlan_objmgr_pdev *pdev,
5594 				       uint16_t cw_int, uint32_t dcs_enabled)
5595 {
5596 	struct spectral_samp_msg *msg = NULL;
5597 	struct target_if_spectral_ops *p_sops = NULL;
5598 	struct target_if_spectral *spectral = NULL;
5599 
5600 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
5601 
5602 	if (!spectral) {
5603 		spectral_err("SPECTRAL : Module doesn't exist");
5604 		return;
5605 	}
5606 
5607 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
5608 	if (!p_sops) {
5609 		spectral_err("p_sops is null");
5610 		return;
5611 	}
5612 
5613 	msg  = (struct spectral_samp_msg *)spectral->nl_cb.get_sbuff(
5614 			spectral->pdev_obj,
5615 			SPECTRAL_MSG_INTERFERENCE_NOTIFICATION,
5616 			SPECTRAL_MSG_BUF_NEW);
5617 
5618 	if (msg) {
5619 		msg->int_type = cw_int ?
5620 		    SPECTRAL_DCS_INT_CW : SPECTRAL_DCS_INT_WIFI;
5621 		msg->dcs_enabled = dcs_enabled;
5622 		msg->signature = SPECTRAL_SIGNATURE;
5623 		p_sops->get_mac_address(spectral, msg->macaddr);
5624 		if (spectral->send_phy_data
5625 				(pdev,
5626 				 SPECTRAL_MSG_INTERFERENCE_NOTIFICATION) == 0)
5627 			spectral->spectral_sent_msg++;
5628 	}
5629 }
5630 qdf_export_symbol(target_if_spectral_send_intf_found_msg);
5631