xref: /wlan-dirver/qca-wifi-host-cmn/target_if/spectral/target_if_spectral.c (revision 6ecd284e5a94a1c96e26d571dd47419ac305990d)
1 /*
2  * Copyright (c) 2011,2017-2018 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_ucfg.h>
29 #include <reg_services_public_struct.h>
30 #ifdef CONFIG_WIN
31 #include <wlan_mlme_dispatcher.h>
32 #endif /*CONFIG_WIN*/
33 #include <reg_services_public_struct.h>
34 #include <target_if_spectral_sim.h>
35 #include <target_if.h>
36 #include <qdf_module.h>
37 /**
38  * @spectral_ops - Spectral function table, holds the Spectral functions that
39  * depend on whether the architecture is Direct Attach or Offload. This is used
40  * to populate the actual Spectral function table present in the Spectral
41  * module.
42  */
43 struct target_if_spectral_ops spectral_ops;
44 int spectral_debug_level = DEBUG_SPECTRAL;
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 {
59 	struct wlan_objmgr_pdev *pdev = NULL;
60 	struct wlan_objmgr_vdev *first_vdev = NULL;
61 
62 	qdf_assert_always(spectral);
63 	pdev = spectral->pdev_obj;
64 	qdf_assert_always(pdev);
65 
66 	if (wlan_objmgr_pdev_try_get_ref(pdev, WLAN_SPECTRAL_ID) !=
67 	    QDF_STATUS_SUCCESS) {
68 		spectral_err("Unable to get pdev reference.");
69 		return NULL;
70 	}
71 
72 	wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
73 					  target_if_spectral_get_firstvdev_pdev,
74 					  &first_vdev, 0, WLAN_SPECTRAL_ID);
75 
76 	wlan_objmgr_pdev_release_ref(pdev, WLAN_SPECTRAL_ID);
77 
78 	if (wlan_objmgr_vdev_try_get_ref(first_vdev, WLAN_SPECTRAL_ID) !=
79 			QDF_STATUS_SUCCESS)
80 		first_vdev = NULL;
81 
82 	if (!first_vdev) {
83 		spectral_warn("Unable to get first vdev of pdev.");
84 		return NULL;
85 	}
86 
87 	return first_vdev;
88 }
89 
90 /**
91  * target_if_send_vdev_spectral_configure_cmd() - Send WMI command to configure
92  * spectral parameters
93  * @spectral: Pointer to Spectral target_if internal private data
94  * @param: Pointer to spectral_config giving the Spectral configuration
95  *
96  * Return: QDF_STATUS_SUCCESS on success, negative error code on failure
97  */
98 static int
99 target_if_send_vdev_spectral_configure_cmd(struct target_if_spectral *spectral,
100 					   struct spectral_config *param)
101 {
102 	struct vdev_spectral_configure_params sparam;
103 	struct wlan_objmgr_pdev *pdev = NULL;
104 	struct wlan_objmgr_vdev *vdev = NULL;
105 
106 	qdf_assert_always(spectral && param);
107 
108 	pdev = spectral->pdev_obj;
109 
110 	qdf_assert_always(pdev);
111 
112 	vdev = target_if_spectral_get_vdev(spectral);
113 	if (!vdev)
114 		return QDF_STATUS_E_NOENT;
115 
116 	qdf_mem_set(&sparam, sizeof(sparam), 0);
117 
118 	sparam.vdev_id = wlan_vdev_get_id(vdev);
119 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
120 
121 	sparam.count = param->ss_count;
122 	sparam.period = param->ss_period;
123 	sparam.spectral_pri = param->ss_spectral_pri;
124 	sparam.fft_size = param->ss_fft_size;
125 	sparam.gc_enable = param->ss_gc_ena;
126 	sparam.restart_enable = param->ss_restart_ena;
127 	sparam.noise_floor_ref = param->ss_noise_floor_ref;
128 	sparam.init_delay = param->ss_init_delay;
129 	sparam.nb_tone_thr = param->ss_nb_tone_thr;
130 	sparam.str_bin_thr = param->ss_str_bin_thr;
131 	sparam.wb_rpt_mode = param->ss_wb_rpt_mode;
132 	sparam.rssi_rpt_mode = param->ss_rssi_rpt_mode;
133 	sparam.rssi_thr = param->ss_rssi_thr;
134 	sparam.pwr_format = param->ss_pwr_format;
135 	sparam.rpt_mode = param->ss_rpt_mode;
136 	sparam.bin_scale = param->ss_bin_scale;
137 	sparam.dbm_adj = param->ss_dbm_adj;
138 	sparam.chn_mask = param->ss_chn_mask;
139 
140 	return spectral->param_wmi_cmd_ops.wmi_spectral_configure_cmd_send(
141 				GET_WMI_HDL_FROM_PDEV(pdev), &sparam);
142 }
143 
144 /**
145  * target_if_send_vdev_spectral_enable_cmd() - Send WMI command to
146  * enable/disable Spectral
147  * @spectral: Pointer to Spectral target_if internal private data
148  * @is_spectral_active_valid: Flag to indicate if spectral activate (trigger) is
149  * valid
150  * @is_spectral_active: Value of spectral activate
151  * @is_spectral_enabled_valid: Flag to indicate if spectral enable is valid
152  * @is_spectral_enabled: Value of spectral enable
153  *
154  * Return: QDF_STATUS_SUCCESS on success, negative error code on failure
155  */
156 static int
157 target_if_send_vdev_spectral_enable_cmd(struct target_if_spectral *spectral,
158 					uint8_t is_spectral_active_valid,
159 					uint8_t is_spectral_active,
160 					uint8_t is_spectral_enabled_valid,
161 					uint8_t is_spectral_enabled)
162 {
163 	struct vdev_spectral_enable_params param;
164 	struct wlan_objmgr_pdev *pdev = NULL;
165 	struct wlan_objmgr_vdev *vdev = NULL;
166 
167 	qdf_assert_always(spectral);
168 
169 	pdev = spectral->pdev_obj;
170 
171 	qdf_assert_always(pdev);
172 
173 	vdev = target_if_spectral_get_vdev(spectral);
174 	if (!vdev)
175 		return QDF_STATUS_E_NOENT;
176 
177 	qdf_mem_set(&param, sizeof(param), 0);
178 
179 	param.vdev_id = wlan_vdev_get_id(vdev);
180 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
181 
182 	param.active_valid = is_spectral_active_valid;
183 	param.enabled_valid = is_spectral_enabled_valid;
184 	param.active = is_spectral_active;
185 	param.enabled = is_spectral_enabled;
186 
187 	return spectral->param_wmi_cmd_ops.wmi_spectral_enable_cmd_send(
188 				GET_WMI_HDL_FROM_PDEV(pdev), &param);
189 }
190 
191 /**
192  * target_if_spectral_info_init_defaults() - Helper function to load defaults
193  * for Spectral information (parameters and state) into cache.
194  * @spectral: Pointer to Spectral target_if internal private data
195  *
196  * It is assumed that the caller has obtained the requisite lock if applicable.
197  * Note that this is currently treated as a temporary function.  Ideally, we
198  * would like to get defaults from the firmware.
199  *
200  * Return: QDF_STATUS_SUCCESS on success, negative error code on failure
201  */
202 static int
203 target_if_spectral_info_init_defaults(struct target_if_spectral *spectral)
204 {
205 	struct target_if_spectral_param_state_info *info =
206 		&spectral->param_info;
207 	struct wlan_objmgr_vdev *vdev = NULL;
208 
209 	/* State */
210 	info->osps_cache.osc_spectral_active = SPECTRAL_SCAN_ACTIVE_DEFAULT;
211 
212 	info->osps_cache.osc_spectral_enabled = SPECTRAL_SCAN_ENABLE_DEFAULT;
213 
214 	/* Parameters */
215 	info->osps_cache.osc_params.ss_count = SPECTRAL_SCAN_COUNT_DEFAULT;
216 
217 	info->osps_cache.osc_params.ss_period = SPECTRAL_SCAN_PERIOD_DEFAULT;
218 
219 	info->osps_cache.osc_params.ss_spectral_pri =
220 	    SPECTRAL_SCAN_PRIORITY_DEFAULT;
221 
222 	info->osps_cache.osc_params.ss_fft_size =
223 	    SPECTRAL_SCAN_FFT_SIZE_DEFAULT;
224 
225 	info->osps_cache.osc_params.ss_gc_ena = SPECTRAL_SCAN_GC_ENA_DEFAULT;
226 
227 	info->osps_cache.osc_params.ss_restart_ena =
228 	    SPECTRAL_SCAN_RESTART_ENA_DEFAULT;
229 
230 	info->osps_cache.osc_params.ss_noise_floor_ref =
231 	    SPECTRAL_SCAN_NOISE_FLOOR_REF_DEFAULT;
232 
233 	info->osps_cache.osc_params.ss_init_delay =
234 	    SPECTRAL_SCAN_INIT_DELAY_DEFAULT;
235 
236 	info->osps_cache.osc_params.ss_nb_tone_thr =
237 	    SPECTRAL_SCAN_NB_TONE_THR_DEFAULT;
238 
239 	info->osps_cache.osc_params.ss_str_bin_thr =
240 	    SPECTRAL_SCAN_STR_BIN_THR_DEFAULT;
241 
242 	info->osps_cache.osc_params.ss_wb_rpt_mode =
243 	    SPECTRAL_SCAN_WB_RPT_MODE_DEFAULT;
244 
245 	info->osps_cache.osc_params.ss_rssi_rpt_mode =
246 	    SPECTRAL_SCAN_RSSI_RPT_MODE_DEFAULT;
247 
248 	info->osps_cache.osc_params.ss_rssi_thr =
249 	    SPECTRAL_SCAN_RSSI_THR_DEFAULT;
250 
251 	info->osps_cache.osc_params.ss_pwr_format =
252 	    SPECTRAL_SCAN_PWR_FORMAT_DEFAULT;
253 
254 	info->osps_cache.osc_params.ss_rpt_mode =
255 	    SPECTRAL_SCAN_RPT_MODE_DEFAULT;
256 
257 	info->osps_cache.osc_params.ss_bin_scale =
258 	    SPECTRAL_SCAN_BIN_SCALE_DEFAULT;
259 
260 	info->osps_cache.osc_params.ss_dbm_adj = SPECTRAL_SCAN_DBM_ADJ_DEFAULT;
261 
262 	vdev = target_if_spectral_get_vdev(spectral);
263 	if (!vdev)
264 		return QDF_STATUS_E_NOENT;
265 
266 	info->osps_cache.osc_params.ss_chn_mask =
267 	    wlan_vdev_mlme_get_rxchainmask(vdev);
268 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
269 
270 	/* The cache is now valid */
271 	info->osps_cache.osc_is_valid = 1;
272 
273 	return QDF_STATUS_SUCCESS;
274 }
275 
276 #ifdef OL_SPECTRAL_DEBUG_CONFIG_INTERACTIONS
277 /**
278  * target_if_log_read_spectral_active() - Helper function to log whether
279  * spectral is active after reading cache
280  * @function_name: Function name
281  * @output: whether spectral is active or not
282  *
283  * Helper function to log whether spectral is active after reading cache
284  *
285  * Return: none
286  */
287 static void
288 target_if_log_read_spectral_active(
289 	const char *function_name,
290 	unsigned char output)
291 {
292 	spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ACTIVE. Returning val=%u",
293 		       function_name, output);
294 }
295 
296 /**
297  * target_if_log_read_spectral_enabled() - Helper function to log whether
298  * spectral is enabled after reading cache
299  * @function_name: Function name
300  * @output: whether spectral is enabled or not
301  *
302  * Helper function to log whether spectral is enabled after reading cache
303  *
304  * Return: none
305  */
306 static void
307 target_if_log_read_spectral_enabled(
308 	const char *function_name,
309 	unsigned char output)
310 {
311 	spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ENABLED. Returning val=%u",
312 		       function_name, output);
313 }
314 
315 /**
316  * target_if_log_read_spectral_enabled() - Helper function to log spectral
317  * parameters after reading cache
318  * @function_name: Function name
319  * @pparam: Spectral parameters
320  *
321  * Helper function to log spectral parameters after reading cache
322  *
323  * Return: none
324  */
325 static void
326 target_if_log_read_spectral_params(
327 	const char *function_name,
328 	struct spectral_config *pparam)
329 {
330 	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\n",
331 		       function_name,
332 		       pparam->ss_count,
333 		       pparam->ss_period,
334 		       pparam->ss_spectral_pri,
335 		       pparam->ss_fft_size,
336 		       pparam->ss_gc_ena,
337 		       pparam->ss_restart_ena,
338 		       (int8_t)pparam->ss_noise_floor_ref,
339 		       pparam->ss_init_delay,
340 		       pparam->ss_nb_tone_thr,
341 		       pparam->ss_str_bin_thr,
342 		       pparam->ss_wb_rpt_mode,
343 		       pparam->ss_rssi_rpt_mode,
344 		       (int8_t)pparam->ss_rssi_thr,
345 		       pparam->ss_pwr_format,
346 		       pparam->ss_rpt_mode,
347 		       pparam->ss_bin_scale,
348 		       pparam->ss_dbm_adj,
349 		       pparam->ss_chn_mask);
350 }
351 
352 /**
353  * target_if_log_read_spectral_active_catch_validate() - Helper function to
354  * log whether spectral is active after intializing the cache
355  * @function_name: Function name
356  * @output: whether spectral is active or not
357  *
358  * Helper function to log whether spectral is active after intializing cache
359  *
360  * Return: none
361  */
362 static void
363 target_if_log_read_spectral_active_catch_validate(
364 	const char *function_name,
365 	unsigned char output)
366 {
367 	spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ACTIVE on initial cache validation\nReturning val=%u",
368 		       function_name, output);
369 }
370 
371 /**
372  * target_if_log_read_spectral_enabled_catch_validate() - Helper function to
373  * log whether spectral is enabled after intializing the cache
374  * @function_name: Function name
375  * @output: whether spectral is enabled or not
376  *
377  * Helper function to log whether spectral is enabled after intializing cache
378  *
379  * Return: none
380  */
381 static void
382 target_if_log_read_spectral_enabled_catch_validate(
383 	const char *function_name,
384 	unsigned char output)
385 {
386 	spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ENABLED on initial cache validation\nReturning val=%u\n",
387 		       function_name, output);
388 }
389 
390 /**
391  * target_if_log_read_spectral_params_catch_validate() - Helper function to
392  * log spectral parameters after intializing the cache
393  * @function_name: Function name
394  * @pparam: Spectral parameters
395  *
396  * Helper function to log spectral parameters after intializing the cache
397  *
398  * Return: none
399  */
400 static void
401 target_if_log_read_spectral_params_catch_validate(
402 	const char *function_name,
403 	struct spectral_config *pparam)
404 {
405 	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",
406 		       function_name,
407 		       pparam->ss_count,
408 		       pparam->ss_period,
409 		       pparam->ss_spectral_pri,
410 		       pparam->ss_fft_size,
411 		       pparam->ss_gc_ena,
412 		       pparam->ss_restart_ena,
413 		       (int8_t)pparam->ss_noise_floor_ref,
414 		       pparam->ss_init_delay,
415 		       pparam->ss_nb_tone_thr,
416 		       pparam->ss_str_bin_thr,
417 		       pparam->ss_wb_rpt_mode,
418 		       pparam->ss_rssi_rpt_mode,
419 		       (int8_t)pparam->ss_rssi_thr,
420 		       pparam->ss_pwr_format,
421 		       pparam->ss_rpt_mode,
422 		       pparam->ss_bin_scale,
423 		       pparam->ss_dbm_adj, pparam->ss_chn_mask);
424 }
425 
426 #else
427 static void
428 target_if_log_read_spectral_active(
429 	const char *function_name,
430 	unsigned char output)
431 {
432 }
433 
434 static void
435 target_if_log_read_spectral_enabled(
436 	const char *function_name,
437 	unsigned char output)
438 {
439 }
440 
441 static void
442 target_if_log_read_spectral_params(
443 	const char *function_name,
444 	struct spectral_config *pparam)
445 {
446 }
447 
448 static void
449 target_if_log_read_spectral_active_catch_validate(
450 	const char *function_name,
451 	unsigned char output)
452 {
453 }
454 
455 static void
456 target_if_log_read_spectral_enabled_catch_validate(
457 	const char *function_name,
458 	unsigned char output)
459 {
460 }
461 
462 static void
463 target_if_log_read_spectral_params_catch_validate(
464 	const char *function_name,
465 	struct spectral_config *pparam)
466 {
467 }
468 #endif
469 
470 /**
471  * target_if_spectral_info_read() - Read spectral information from the cache.
472  * @spectral: Pointer to Spectral target_if internal private data
473  * @specifier: target_if_spectral_info enumeration specifying which
474  * information is required
475  * @output: Void output pointer into which the information will be read
476  * @output_len: size of object pointed to by output pointer
477  *
478  * Read spectral parameters or the desired state information from the cache.
479  *
480  * Return: 0 on success, negative error code on failure
481  */
482 static int
483 target_if_spectral_info_read(
484 	struct target_if_spectral *spectral,
485 	enum target_if_spectral_info specifier,
486 	void *output, int output_len)
487 {
488 	/*
489 	 * Note: This function is designed to be able to accommodate
490 	 * WMI reads for defaults, non-cacheable information, etc
491 	 * if required.
492 	 */
493 	struct target_if_spectral_param_state_info *info =
494 		&spectral->param_info;
495 	int is_cacheable = 0;
496 	int init_def_retval = 0;
497 
498 	if (!output)
499 		return -EINVAL;
500 
501 	switch (specifier) {
502 	case TARGET_IF_SPECTRAL_INFO_ACTIVE:
503 		if (output_len != sizeof(info->osps_cache.osc_spectral_active))
504 			return -EINVAL;
505 		is_cacheable = 1;
506 		break;
507 
508 	case TARGET_IF_SPECTRAL_INFO_ENABLED:
509 		if (output_len != sizeof(info->osps_cache.osc_spectral_enabled))
510 			return -EINVAL;
511 		is_cacheable = 1;
512 		break;
513 
514 	case TARGET_IF_SPECTRAL_INFO_PARAMS:
515 		if (output_len != sizeof(info->osps_cache.osc_params))
516 			return -EINVAL;
517 		is_cacheable = 1;
518 		break;
519 
520 	default:
521 		spectral_err("Unknown target_if_spectral_info specifier");
522 		return -EINVAL;
523 	}
524 
525 	qdf_spin_lock(&info->osps_lock);
526 
527 	if (is_cacheable) {
528 		if (info->osps_cache.osc_is_valid) {
529 			switch (specifier) {
530 			case TARGET_IF_SPECTRAL_INFO_ACTIVE:
531 				qdf_mem_copy(
532 				  output,
533 				  &info->osps_cache.osc_spectral_active,
534 				  sizeof(info->osps_cache.osc_spectral_active));
535 
536 				target_if_log_read_spectral_active(
537 					__func__,
538 					*((unsigned char *)output));
539 				break;
540 
541 			case TARGET_IF_SPECTRAL_INFO_ENABLED:
542 				qdf_mem_copy(
543 				  output,
544 				  &info->osps_cache.osc_spectral_enabled,
545 				  sizeof(
546 					info->osps_cache.osc_spectral_enabled));
547 
548 				target_if_log_read_spectral_enabled(
549 					__func__,
550 					*((unsigned char *)output));
551 				break;
552 
553 			case TARGET_IF_SPECTRAL_INFO_PARAMS:
554 				qdf_mem_copy(
555 				  output,
556 				  &info->osps_cache.osc_params,
557 				  sizeof(info->osps_cache.osc_params));
558 
559 				target_if_log_read_spectral_params(
560 					__func__,
561 					(struct spectral_config *)output);
562 				break;
563 
564 			default:
565 				/* We can't reach this point */
566 				break;
567 			}
568 			qdf_spin_unlock(&info->osps_lock);
569 			return 0;
570 		}
571 	}
572 
573 	/* Cache is invalid */
574 
575 	/*
576 	 * If WMI Reads are implemented to fetch defaults/non-cacheable info,
577 	 * then the below implementation will change
578 	 */
579 	init_def_retval = target_if_spectral_info_init_defaults(spectral);
580 	if (init_def_retval != QDF_STATUS_SUCCESS) {
581 		qdf_spin_unlock(&info->osps_lock);
582 		if (init_def_retval == QDF_STATUS_E_NOENT)
583 			return -ENOENT;
584 		else
585 			return -EINVAL;
586 	}
587 	/* target_if_spectral_info_init_defaults() has set cache to valid */
588 
589 	switch (specifier) {
590 	case TARGET_IF_SPECTRAL_INFO_ACTIVE:
591 		qdf_mem_copy(output,
592 			     &info->osps_cache.osc_spectral_active,
593 			     sizeof(info->osps_cache.osc_spectral_active));
594 
595 		target_if_log_read_spectral_active_catch_validate(
596 			__func__,
597 			*((unsigned char *)output));
598 		break;
599 
600 	case TARGET_IF_SPECTRAL_INFO_ENABLED:
601 		qdf_mem_copy(output,
602 			     &info->osps_cache.osc_spectral_enabled,
603 			     sizeof(info->osps_cache.osc_spectral_enabled));
604 
605 		target_if_log_read_spectral_enabled_catch_validate(
606 			__func__,
607 			*((unsigned char *)output));
608 		break;
609 
610 	case TARGET_IF_SPECTRAL_INFO_PARAMS:
611 		qdf_mem_copy(output,
612 			     &info->osps_cache.osc_params,
613 			     sizeof(info->osps_cache.osc_params));
614 
615 		target_if_log_read_spectral_params_catch_validate(
616 			__func__,
617 			(struct spectral_config *)output);
618 
619 		break;
620 
621 	default:
622 		/* We can't reach this point */
623 		break;
624 	}
625 
626 	qdf_spin_unlock(&info->osps_lock);
627 
628 	return 0;
629 }
630 
631 #ifdef OL_SPECTRAL_DEBUG_CONFIG_INTERACTIONS
632 /**
633  * target_if_log_write_spectral_active() - Helper function to log inputs and
634  * return value of call to configure the Spectral 'active' configuration,
635  * TARGET_IF_SPECTRAL_INFO_ACTIVE into firmware
636  * @function_name: Function name in which this is called
637  * @pval: whether spectral is active or not
638  * @ret: return value of the firmware write function
639  *
640  * Return: none
641  */
642 static void
643 target_if_log_write_spectral_active(
644 	const char *function_name,
645 	uint8_t pval,
646 	int ret)
647 {
648 	spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ACTIVE with val=%u status=%d",
649 		       function_name, pval, ret);
650 }
651 
652 /**
653  * target_if_log_write_spectral_enabled() - Helper function to log inputs and
654  * return value of call to configure the Spectral 'enabled' configuration,
655  * TARGET_IF_SPECTRAL_INFO_ENABLED into firmware
656  * @function_name: Function name in which this is called
657  * @pval: whether spectral is enabled or not
658  * @ret: return value of the firmware write function
659  *
660  * Return: none
661  */
662 static void
663 target_if_log_write_spectral_enabled(
664 	const char *function_name,
665 	uint8_t pval,
666 	int ret)
667 {
668 	spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ENABLED with val=%u status=%d",
669 		       function_name, pval, ret);
670 }
671 
672 /**
673  * target_if_log_write_spectral_params() - Helper function to log inputs and
674  * return value of call to configure Spectral parameters,
675  * TARGET_IF_SPECTRAL_INFO_PARAMS into firmware
676  * @param: Spectral parameters
677  * @function_name: Function name in which this is called
678  * @ret: return value of the firmware write function
679  *
680  * Return: none
681  */
682 static void
683 target_if_log_write_spectral_params(
684 	struct spectral_config *param,
685 	const char *function_name,
686 	int ret)
687 {
688 	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\nstatus = %d",
689 		       function_name,
690 		       param->ss_count,
691 		       param->ss_period,
692 		       param->ss_spectral_pri,
693 		       param->ss_fft_size,
694 		       param->ss_gc_ena,
695 		       param->ss_restart_ena,
696 		       (int8_t)param->ss_noise_floor_ref,
697 		       param->ss_init_delay,
698 		       param->ss_nb_tone_thr,
699 		       param->ss_str_bin_thr,
700 		       param->ss_wb_rpt_mode,
701 		       param->ss_rssi_rpt_mode,
702 		       (int8_t)param->ss_rssi_thr,
703 		       param->ss_pwr_format,
704 		       param->ss_rpt_mode,
705 		       param->ss_bin_scale,
706 		       param->ss_dbm_adj, param->ss_chn_mask, ret);
707 }
708 #else
709 static void
710 target_if_log_write_spectral_active(
711 	const char *function_name,
712 	uint8_t pval,
713 	int ret)
714 {
715 }
716 
717 static void
718 target_if_log_write_spectral_enabled(
719 	const char *function_name,
720 	uint8_t pval,
721 	int ret)
722 {
723 }
724 
725 static void
726 target_if_log_write_spectral_params(
727 	struct spectral_config *param,
728 	const char *function_name,
729 	int ret)
730 {
731 }
732 
733 #endif
734 
735 /**
736  * target_if_spectral_info_write() - Write Spectral information to the
737  * firmware, and update cache
738  * @spectral: Pointer to Spectral target_if internal private data
739  * @specifier: target_if_spectral_info enumeration specifying which
740  * information is involved
741  * @input: void input pointer containing the information to be written
742  * @input_len: size of object pointed to by input pointer
743  *
744  * Write Spectral parameters or the desired state information to
745  * the firmware, and update cache
746  *
747  * Return: 0 on success, negative error code on failure
748  */
749 static int
750 target_if_spectral_info_write(
751 	struct target_if_spectral *spectral,
752 	enum target_if_spectral_info specifier,
753 	void *input, int input_len)
754 {
755 	struct target_if_spectral_param_state_info *info =
756 		&spectral->param_info;
757 	int ret;
758 	uint8_t *pval = NULL;
759 	struct spectral_config *param = NULL;
760 
761 	if (!input)
762 		return -EINVAL;
763 
764 	switch (specifier) {
765 	case TARGET_IF_SPECTRAL_INFO_ACTIVE:
766 		if (input_len != sizeof(info->osps_cache.osc_spectral_active))
767 			return -EINVAL;
768 
769 		pval = (uint8_t *)input;
770 
771 		qdf_spin_lock(&info->osps_lock);
772 		ret = target_if_send_vdev_spectral_enable_cmd(spectral,
773 							      1, *pval, 0, 0);
774 
775 		target_if_log_write_spectral_active(
776 			__func__,
777 			*pval,
778 			ret);
779 
780 		if (ret < 0) {
781 			spectral_err("target_if_send_vdev_spectral_enable_cmd failed with error=%d",
782 				     ret);
783 			qdf_spin_unlock(&info->osps_lock);
784 			return ret;
785 		}
786 
787 		info->osps_cache.osc_spectral_active = *pval;
788 		qdf_spin_unlock(&info->osps_lock);
789 		break;
790 
791 	case TARGET_IF_SPECTRAL_INFO_ENABLED:
792 		if (input_len != sizeof(info->osps_cache.osc_spectral_enabled))
793 			return -EINVAL;
794 
795 		pval = (uint8_t *)input;
796 
797 		qdf_spin_lock(&info->osps_lock);
798 		ret = target_if_send_vdev_spectral_enable_cmd(spectral,
799 							      0, 0, 1, *pval);
800 
801 		target_if_log_write_spectral_enabled(
802 			__func__,
803 			*pval,
804 			ret);
805 
806 		if (ret < 0) {
807 			spectral_err("target_if_send_vdev_spectral_enable_cmd failed with error=%d",
808 				     ret);
809 			qdf_spin_unlock(&info->osps_lock);
810 			return ret;
811 		}
812 
813 		info->osps_cache.osc_spectral_enabled = *pval;
814 		qdf_spin_unlock(&info->osps_lock);
815 		break;
816 
817 	case TARGET_IF_SPECTRAL_INFO_PARAMS:
818 		if (input_len != sizeof(info->osps_cache.osc_params))
819 			return -EINVAL;
820 
821 		param = (struct spectral_config *)input;
822 
823 		qdf_spin_lock(&info->osps_lock);
824 		ret = target_if_send_vdev_spectral_configure_cmd(spectral,
825 								 param);
826 
827 		target_if_log_write_spectral_params(
828 			param,
829 			__func__,
830 			ret);
831 
832 		if (ret < 0) {
833 			spectral_err("target_if_send_vdev_spectral_configure_cmd failed with error=%d",
834 				     ret);
835 			qdf_spin_unlock(&info->osps_lock);
836 			return ret;
837 		}
838 
839 		qdf_mem_copy(&info->osps_cache.osc_params,
840 			     param, sizeof(info->osps_cache.osc_params));
841 		qdf_spin_unlock(&info->osps_lock);
842 		break;
843 
844 	default:
845 		spectral_err("Unknown target_if_spectral_info specifier");
846 		return -EINVAL;
847 	}
848 
849 	return 0;
850 }
851 
852 /**
853  * target_if_spectral_get_tsf64() - Function to get the TSF value
854  * @arg: Pointer to handle for Spectral target_if internal private data
855  *
856  * Get the last TSF received in WMI buffer
857  *
858  * Return: TSF value
859  */
860 static uint64_t
861 target_if_spectral_get_tsf64(void *arg)
862 {
863 	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
864 
865 	return spectral->tsf64;
866 }
867 
868 /**
869  * target_if_spectral_get_capability() - Function to get whether a
870  * given Spectral hardware capability is available
871  * @arg: Pointer to handle for Spectral target_if internal private data
872  * @type: Spectral hardware capability type
873  *
874  * Get whether a given Spectral hardware capability is available
875  *
876  * Return: True if the capability is available, false if the capability is not
877  * available
878  */
879 uint32_t
880 target_if_spectral_get_capability(void *arg, enum spectral_capability_type type)
881 {
882 	int status = STATUS_FAIL;
883 
884 	switch (type) {
885 	case SPECTRAL_CAP_PHYDIAG:
886 	case SPECTRAL_CAP_RADAR:
887 	case SPECTRAL_CAP_SPECTRAL_SCAN:
888 	case SPECTRAL_CAP_ADVNCD_SPECTRAL_SCAN:
889 		status = STATUS_PASS;
890 		break;
891 	default:
892 		status = STATUS_FAIL;
893 	}
894 	return status;
895 }
896 
897 /**
898  * target_if_spectral_set_rxfilter() - Set the RX Filter before Spectral start
899  * @arg: Pointer to handle for Spectral target_if internal private data
900  * @rxfilter: Rx filter to be used
901  *
902  * Note: This is only a placeholder function. It is not currently required since
903  * FW should be taking care of setting the required filters.
904  *
905  * Return: 0
906  */
907 uint32_t
908 target_if_spectral_set_rxfilter(void *arg, int rxfilter)
909 {
910 	/*
911 	 * Will not be required since enabling of spectral in firmware
912 	 * will take care of this
913 	 */
914 	return 0;
915 }
916 
917 /**
918  * target_if_spectral_get_rxfilter() - Get the current RX Filter settings
919  * @arg: Pointer to handle for Spectral target_if internal private data
920  *
921  * Note: This is only a placeholder function. It is not currently required since
922  * FW should be taking care of setting the required filters.
923  *
924  * Return: 0
925  */
926 uint32_t
927 target_if_spectral_get_rxfilter(void *arg)
928 {
929 	/*
930 	 * Will not be required since enabling of spectral in firmware
931 	 * will take care of this
932 	 */
933 	return 0;
934 }
935 
936 /**
937  * target_if_sops_is_spectral_active() - Get whether Spectral is active
938  * @arg: Pointer to handle for Spectral target_if internal private data
939  *
940  * Function to check whether Spectral is active
941  *
942  * Return: True if Spectral is active, false if Spectral is not active
943  */
944 uint32_t
945 target_if_sops_is_spectral_active(void *arg)
946 {
947 	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
948 	uint8_t val = 0;
949 	int ret;
950 
951 	ret = target_if_spectral_info_read(
952 		spectral,
953 		TARGET_IF_SPECTRAL_INFO_ACTIVE,
954 		&val, sizeof(val));
955 
956 	if (ret != 0) {
957 		/*
958 		 * Could not determine if Spectral is active.
959 		 * Return false as a safe value.
960 		 * XXX: Consider changing the function prototype
961 		 * to be able to indicate failure to fetch value.
962 		 */
963 		return 0;
964 	}
965 
966 	return val;
967 }
968 
969 /**
970  * target_if_sops_is_spectral_enabled() - Get whether Spectral is enabled
971  * @arg: Pointer to handle for Spectral target_if internal private data
972  *
973  * Function to check whether Spectral is enabled
974  *
975  * Return: True if Spectral is enabled, false if Spectral is not enabled
976  */
977 uint32_t
978 target_if_sops_is_spectral_enabled(void *arg)
979 {
980 	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
981 	uint8_t val = 0;
982 	int ret;
983 
984 	ret = target_if_spectral_info_read(
985 		spectral,
986 		TARGET_IF_SPECTRAL_INFO_ENABLED,
987 		&val, sizeof(val));
988 
989 	if (ret != 0) {
990 		/*
991 		 * Could not determine if Spectral is enabled.
992 		 * Return false as a safe value.
993 		 * XXX: Consider changing the function prototype
994 		 * to be able to indicate failure to fetch value.
995 		 */
996 		return 0;
997 	}
998 
999 	return val;
1000 }
1001 
1002 /**
1003  * target_if_sops_start_spectral_scan() - Start Spectral scan
1004  * @arg: Pointer to handle for Spectral target_if internal private data
1005  *
1006  * Function to start spectral scan
1007  *
1008  * Return: 0 on success else failure
1009  */
1010 uint32_t
1011 target_if_sops_start_spectral_scan(void *arg)
1012 {
1013 	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
1014 	uint8_t val = 1;
1015 	uint8_t enabled = 0;
1016 	int ret;
1017 
1018 	ret = target_if_spectral_info_read(
1019 		spectral,
1020 		TARGET_IF_SPECTRAL_INFO_ENABLED,
1021 		&enabled, sizeof(enabled));
1022 
1023 	if (ret != 0) {
1024 		/*
1025 		 * Could not determine if Spectral is enabled. Assume we need
1026 		 * to enable it
1027 		 */
1028 		enabled = 0;
1029 	}
1030 
1031 	if (!enabled) {
1032 		ret = target_if_spectral_info_write(
1033 			spectral,
1034 			TARGET_IF_SPECTRAL_INFO_ENABLED,
1035 			&val, sizeof(val));
1036 
1037 		if (ret != 0)
1038 			return ret;
1039 	}
1040 
1041 	ret = target_if_spectral_info_write(
1042 		spectral,
1043 		TARGET_IF_SPECTRAL_INFO_ACTIVE,
1044 		&val, sizeof(val));
1045 
1046 	if (ret != 0)
1047 		return ret;
1048 
1049 	return 0;
1050 }
1051 
1052 /**
1053  * target_if_sops_stop_spectral_scan() - Stop Spectral scan
1054  * @arg: Pointer to handle for Spectral target_if internal private data
1055  *
1056  * Function to stop spectral scan
1057  *
1058  * Return: 0 on success else failure
1059  */
1060 uint32_t
1061 target_if_sops_stop_spectral_scan(void *arg)
1062 {
1063 	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
1064 	uint8_t val = 0;
1065 	int tempret, ret = 0;
1066 
1067 	tempret = target_if_spectral_info_write(
1068 			spectral,
1069 			TARGET_IF_SPECTRAL_INFO_ACTIVE,
1070 			&val, sizeof(val));
1071 
1072 	if (tempret != 0)
1073 		ret = tempret;
1074 
1075 	tempret = target_if_spectral_info_write(
1076 			spectral,
1077 			TARGET_IF_SPECTRAL_INFO_ENABLED,
1078 			&val, sizeof(val));
1079 
1080 	if (tempret != 0)
1081 		ret = tempret;
1082 
1083 	return ret;
1084 }
1085 
1086 /**
1087  * target_if_spectral_get_extension_channel() - Get the Extension channel
1088  * @arg: Pointer to handle for Spectral target_if internal private data
1089  *
1090  * Function to get the current Extension channel (in MHz)
1091  *
1092  * Return: Current Extension channel (in MHz) on success, 0 on failure or if
1093  * extension channel is not present.
1094  */
1095 uint32_t
1096 target_if_spectral_get_extension_channel(void *arg)
1097 {
1098 	/*
1099 	 * XXX: Once we expand to use cases where Spectral could be activated
1100 	 * without a channel being set to VDEV, we need to consider returning a
1101 	 * negative value in case of failure and having all callers handle this.
1102 	 */
1103 
1104 	struct target_if_spectral *spectral = NULL;
1105 	struct wlan_objmgr_vdev *vdev = NULL;
1106 	uint16_t sec20chan_freq = 0;
1107 
1108 	qdf_assert_always(arg);
1109 	spectral = (struct target_if_spectral *)arg;
1110 
1111 	vdev = target_if_spectral_get_vdev(spectral);
1112 	if (!vdev)
1113 		return 0;
1114 
1115 	if (target_if_vdev_get_sec20chan_freq_mhz(vdev, &sec20chan_freq) < 0) {
1116 		wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
1117 		return 0;
1118 	}
1119 
1120 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
1121 
1122 	return sec20chan_freq;
1123 }
1124 
1125 /**
1126  * target_if_spectral_get_current_channel() - Get the current channel
1127  * @arg: Pointer to handle for Spectral target_if internal private data
1128  *
1129  * Function to get the current channel (in MHz)
1130  *
1131  * Return: Current channel (in MHz) on success, 0 on failure
1132  */
1133 uint32_t
1134 target_if_spectral_get_current_channel(void *arg)
1135 {
1136 	/*
1137 	 * XXX: Once we expand to use cases where Spectral could be activated
1138 	 * without a channel being set to VDEV, we need to consider returning a
1139 	 * negative value in case of failure and having all callers handle this.
1140 	 */
1141 
1142 	struct target_if_spectral *spectral = NULL;
1143 	int16_t chan_freq = 0;
1144 	struct wlan_objmgr_vdev *vdev = NULL;
1145 
1146 	qdf_assert_always(arg);
1147 	spectral = (struct target_if_spectral *)arg;
1148 
1149 	vdev = target_if_spectral_get_vdev(spectral);
1150 	if (!vdev)
1151 		return 0;
1152 
1153 	chan_freq = target_if_vdev_get_chan_freq(vdev);
1154 	if (chan_freq < 0) {
1155 		wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
1156 		return 0;
1157 	}
1158 
1159 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
1160 
1161 	return chan_freq;
1162 }
1163 
1164 /**
1165  * target_if_spectral_reset_hw() - Reset the hardware
1166  * @arg: Pointer to handle for Spectral target_if internal private data
1167  *
1168  * This is only a placeholder since it is not currently required in the offload
1169  * case.
1170  *
1171  * Return: 0
1172  */
1173 uint32_t
1174 target_if_spectral_reset_hw(void *arg)
1175 {
1176 	not_yet_implemented();
1177 	return 0;
1178 }
1179 
1180 /**
1181  * target_if_spectral_get_chain_noise_floor() - Get the Chain noise floor from
1182  * Noisefloor history buffer
1183  * @arg: Pointer to handle for Spectral target_if internal private data
1184  * @nf_buf: Pointer to buffer into which chain Noise Floor data should be copied
1185  *
1186  * This is only a placeholder since it is not currently required in the offload
1187  * case.
1188  *
1189  * Return: 0
1190  */
1191 uint32_t
1192 target_if_spectral_get_chain_noise_floor(void *arg, int16_t *nf_buf)
1193 {
1194 	not_yet_implemented();
1195 	return 0;
1196 }
1197 
1198 /**
1199  * target_if_spectral_get_ext_noisefloor() - Get the extension channel
1200  * noisefloor
1201  * @arg: Pointer to handle for Spectral target_if internal private data
1202  *
1203  * This is only a placeholder since it is not currently required in the offload
1204  * case.
1205  *
1206  * Return: 0
1207  */
1208 int8_t
1209 target_if_spectral_get_ext_noisefloor(void *arg)
1210 {
1211 	not_yet_implemented();
1212 	return 0;
1213 }
1214 
1215 /**
1216  * target_if_spectral_get_ctl_noisefloor() - Get the control channel noisefloor
1217  * @arg: Pointer to handle for Spectral target_if internal private data
1218  *
1219  * This is only a placeholder since it is not currently required in the offload
1220  * case.
1221  *
1222  * Return: 0
1223  */
1224 int8_t
1225 target_if_spectral_get_ctl_noisefloor(void *arg)
1226 {
1227 	not_yet_implemented();
1228 	return 0;
1229 }
1230 
1231 /**
1232  * target_if_spectral_sops_configure_params() - Configure user supplied Spectral
1233  *                                         parameters
1234  * @arg: Pointer to handle for Spectral target_if internal private data
1235  * @params: Spectral parameters
1236  *
1237  * Function to configure spectral parameters
1238  *
1239  * Return: 0 on success else failure
1240  */
1241 uint32_t
1242 target_if_spectral_sops_configure_params(
1243 	void *arg, struct spectral_config *params)
1244 {
1245 	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
1246 
1247 	return target_if_spectral_info_write(
1248 		spectral,
1249 		TARGET_IF_SPECTRAL_INFO_PARAMS,
1250 		params, sizeof(*params));
1251 }
1252 
1253 /**
1254  * target_if_spectral_sops_get_params() - Get user configured Spectral
1255  * parameters
1256  * @arg: Pointer to handle for Spectral target_if internal private data
1257  * @params: Pointer to buffer into which Spectral parameters should be copied
1258  *
1259  * Function to get the configured spectral parameters
1260  *
1261  * Return: 0 on success else failure
1262  */
1263 uint32_t
1264 target_if_spectral_sops_get_params(void *arg, struct spectral_config *params)
1265 {
1266 	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
1267 
1268 	return target_if_spectral_info_read(
1269 		spectral,
1270 		TARGET_IF_SPECTRAL_INFO_PARAMS,
1271 		params, sizeof(*params));
1272 }
1273 
1274 /**
1275  * target_if_spectral_get_ent_mask() - Get enterprise mask
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 static uint32_t
1284 target_if_spectral_get_ent_mask(void *arg)
1285 {
1286 	not_yet_implemented();
1287 	return 0;
1288 }
1289 
1290 /**
1291  * target_if_spectral_get_macaddr() - Get radio MAC address
1292  * @arg: Pointer to handle for Spectral target_if internal private data
1293  * @addr: Pointer to buffer into which MAC address should be copied
1294  *
1295  * Function to get the MAC address of the pdev
1296  *
1297  * Return: 0 on success, -1 on failure
1298  */
1299 static uint32_t
1300 target_if_spectral_get_macaddr(void *arg, char *addr)
1301 {
1302 	uint8_t *myaddr = NULL;
1303 	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
1304 	struct wlan_objmgr_pdev *pdev = NULL;
1305 
1306 	pdev = spectral->pdev_obj;
1307 
1308 	wlan_pdev_obj_lock(pdev);
1309 	myaddr = wlan_pdev_get_hw_macaddr(pdev);
1310 	wlan_pdev_obj_unlock(pdev);
1311 	qdf_mem_copy(addr, myaddr, IEEE80211_ADDR_LEN);
1312 
1313 	return 0;
1314 }
1315 
1316 /**
1317  * target_if_init_spectral_capability() - Initialize Spectral capability
1318  * @spectral: Pointer to Spectral target_if internal private data
1319  *
1320  * This is a workaround.
1321  *
1322  * Return: None
1323  */
1324 void
1325 target_if_init_spectral_capability(struct target_if_spectral *spectral)
1326 {
1327 	struct spectral_caps *pcap = &spectral->capability;
1328 
1329 	/* XXX : Workaround: Set Spectral capability */
1330 	pcap = &spectral->capability;
1331 	pcap->phydiag_cap = 1;
1332 	pcap->radar_cap = 1;
1333 	pcap->spectral_cap = 1;
1334 	pcap->advncd_spectral_cap = 1;
1335 }
1336 
1337 #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION
1338 /**
1339  * target_if_init_spectral_simulation_ops() - Initialize spectral target_if
1340  * internal operations with functions related to spectral simulation
1341  * @p_sops: spectral low level ops table
1342  *
1343  * Initialize spectral target_if internal operations with functions
1344  * related to spectral simulation
1345  *
1346  * Return: None
1347  */
1348 static void
1349 target_if_init_spectral_simulation_ops(struct target_if_spectral_ops *p_sops)
1350 {
1351 	/*
1352 	 * Spectral simulation is currently intended for platform transitions
1353 	 * where underlying HW support may not be available for some time.
1354 	 * Hence, we do not currently provide a runtime switch to turn the
1355 	 * simulation on or off.
1356 	 * In case of future requirements where runtime switches are required,
1357 	 * this can be added. But it is suggested to use application layer
1358 	 * simulation as far as possible in such cases, since the main
1359 	 * use of record and replay of samples would concern higher
1360 	 * level sample processing rather than lower level delivery.
1361 	 */
1362 	p_sops->is_spectral_enabled = target_if_spectral_sops_sim_is_enabled;
1363 	p_sops->is_spectral_active = target_if_spectral_sops_sim_is_active;
1364 	p_sops->start_spectral_scan = target_if_spectral_sops_sim_start_scan;
1365 	p_sops->stop_spectral_scan = target_if_spectral_sops_sim_stop_scan;
1366 	p_sops->configure_spectral =
1367 		target_if_spectral_sops_sim_configure_params;
1368 	p_sops->get_spectral_config = target_if_spectral_sops_sim_get_params;
1369 }
1370 
1371 #else
1372 /**
1373  * target_if_init_spectral_simulation_ops() - Initialize spectral target_if
1374  * internal operations
1375  * @p_sops: spectral low level ops table
1376  *
1377  * Return: None
1378  */
1379 static void
1380 target_if_init_spectral_simulation_ops(struct target_if_spectral_ops *p_sops)
1381 {
1382 	p_sops->is_spectral_enabled = target_if_sops_is_spectral_enabled;
1383 	p_sops->is_spectral_active = target_if_sops_is_spectral_active;
1384 	p_sops->start_spectral_scan = target_if_sops_start_spectral_scan;
1385 	p_sops->stop_spectral_scan = target_if_sops_stop_spectral_scan;
1386 	p_sops->configure_spectral = target_if_spectral_sops_configure_params;
1387 	p_sops->get_spectral_config = target_if_spectral_sops_get_params;
1388 }
1389 #endif
1390 
1391 /**
1392  * target_if_init_spectral_ops_common() - Initialize Spectral target_if internal
1393  * operations common to all Spectral chipset generations
1394  *
1395  * Initializes target_if_spectral_ops common to all chipset generations
1396  *
1397  * Return: None
1398  */
1399 static void
1400 target_if_init_spectral_ops_common(void)
1401 {
1402 	struct target_if_spectral_ops *p_sops = &spectral_ops;
1403 
1404 	p_sops->get_tsf64 = target_if_spectral_get_tsf64;
1405 	p_sops->get_capability = target_if_spectral_get_capability;
1406 	p_sops->set_rxfilter = target_if_spectral_set_rxfilter;
1407 	p_sops->get_rxfilter = target_if_spectral_get_rxfilter;
1408 
1409 	target_if_init_spectral_simulation_ops(p_sops);
1410 
1411 	p_sops->get_extension_channel =
1412 	    target_if_spectral_get_extension_channel;
1413 	p_sops->get_ctl_noisefloor = target_if_spectral_get_ctl_noisefloor;
1414 	p_sops->get_ext_noisefloor = target_if_spectral_get_ext_noisefloor;
1415 	p_sops->get_ent_spectral_mask = target_if_spectral_get_ent_mask;
1416 	p_sops->get_mac_address = target_if_spectral_get_macaddr;
1417 	p_sops->get_current_channel = target_if_spectral_get_current_channel;
1418 	p_sops->reset_hw = target_if_spectral_reset_hw;
1419 	p_sops->get_chain_noise_floor =
1420 	    target_if_spectral_get_chain_noise_floor;
1421 }
1422 
1423 /**
1424  * target_if_init_spectral_ops_gen2() - Initialize Spectral target_if internal
1425  * operations specific to Spectral chipset generation 2.
1426  *
1427  * Initializes target_if_spectral_ops specific to Spectral chipset generation 2.
1428  *
1429  * Return: None
1430  */
1431 static void
1432 target_if_init_spectral_ops_gen2(void)
1433 {
1434 	struct target_if_spectral_ops *p_sops = &spectral_ops;
1435 
1436 	p_sops->spectral_process_phyerr = target_if_process_phyerr_gen2;
1437 }
1438 
1439 /**
1440  * target_if_init_spectral_ops_gen3() - Initialize Spectral target_if internal
1441  * operations specific to Spectral chipset generation 3.
1442  *
1443  * Initializes target_if_spectral_ops specific to Spectral chipset generation 3.
1444  *
1445  * Return: None
1446  */
1447 static void
1448 target_if_init_spectral_ops_gen3(void)
1449 {
1450 	struct target_if_spectral_ops *p_sops = &spectral_ops;
1451 
1452 	p_sops->process_spectral_report =
1453 			target_if_spectral_process_report_gen3;
1454 	return;
1455 }
1456 
1457 /**
1458  * target_if_init_spectral_ops() - Initialize target_if internal Spectral
1459  * operations.
1460  * @spectral: Pointer to Spectral target_if internal private data
1461  *
1462  * Initializes all function pointers in target_if_spectral_ops for
1463  * all generations
1464  *
1465  * Return: None
1466  */
1467 static void
1468 target_if_init_spectral_ops(struct target_if_spectral *spectral)
1469 {
1470 	target_if_init_spectral_ops_common();
1471 	if (spectral->spectral_gen == SPECTRAL_GEN2)
1472 		target_if_init_spectral_ops_gen2();
1473 	else if (spectral->spectral_gen == SPECTRAL_GEN3)
1474 		target_if_init_spectral_ops_gen3();
1475 	else
1476 		spectral_err("Invalid Spectral generation");
1477 }
1478 
1479 /*
1480  * Dummy Functions:
1481  * These functions are initially registered to avoid any crashes due to
1482  * invocation of spectral functions before they are registered.
1483  */
1484 
1485 static uint64_t
1486 null_get_tsf64(void *arg)
1487 {
1488 	spectral_ops_not_registered("get_tsf64");
1489 	return 0;
1490 }
1491 
1492 static uint32_t
1493 null_get_capability(void *arg, enum spectral_capability_type type)
1494 {
1495 	/*
1496 	 * TODO : We should have conditional compilation to get the capability
1497 	 *      : We have not yet attahced ATH layer here, so there is no
1498 	 *      : way to check the HAL capbalities
1499 	 */
1500 	spectral_ops_not_registered("get_capability");
1501 
1502 	/* TODO : For the time being, we are returning TRUE */
1503 	return true;
1504 }
1505 
1506 static uint32_t
1507 null_set_rxfilter(void *arg, int rxfilter)
1508 {
1509 	spectral_ops_not_registered("set_rxfilter");
1510 	return 1;
1511 }
1512 
1513 static uint32_t
1514 null_get_rxfilter(void *arg)
1515 {
1516 	spectral_ops_not_registered("get_rxfilter");
1517 	return 0;
1518 }
1519 
1520 static uint32_t
1521 null_is_spectral_active(void *arg)
1522 {
1523 	spectral_ops_not_registered("is_spectral_active");
1524 	return 1;
1525 }
1526 
1527 static uint32_t
1528 null_is_spectral_enabled(void *arg)
1529 {
1530 	spectral_ops_not_registered("is_spectral_enabled");
1531 	return 1;
1532 }
1533 
1534 static uint32_t
1535 null_start_spectral_scan(void *arg)
1536 {
1537 	spectral_ops_not_registered("start_spectral_scan");
1538 	return 1;
1539 }
1540 
1541 static uint32_t
1542 null_stop_spectral_scan(void *arg)
1543 {
1544 	spectral_ops_not_registered("stop_spectral_scan");
1545 	return 1;
1546 }
1547 
1548 static uint32_t
1549 null_get_extension_channel(void *arg)
1550 {
1551 	spectral_ops_not_registered("get_extension_channel");
1552 	return 1;
1553 }
1554 
1555 static int8_t
1556 null_get_ctl_noisefloor(void *arg)
1557 {
1558 	spectral_ops_not_registered("get_ctl_noisefloor");
1559 	return 1;
1560 }
1561 
1562 static int8_t
1563 null_get_ext_noisefloor(void *arg)
1564 {
1565 	spectral_ops_not_registered("get_ext_noisefloor");
1566 	return 0;
1567 }
1568 
1569 static uint32_t
1570 null_configure_spectral(void *arg, struct spectral_config *params)
1571 {
1572 	spectral_ops_not_registered("configure_spectral");
1573 	return 0;
1574 }
1575 
1576 static uint32_t
1577 null_get_spectral_config(void *arg, struct spectral_config *params)
1578 {
1579 	spectral_ops_not_registered("get_spectral_config");
1580 	return 0;
1581 }
1582 
1583 static uint32_t
1584 null_get_ent_spectral_mask(void *arg)
1585 {
1586 	spectral_ops_not_registered("get_ent_spectral_mask");
1587 	return 0;
1588 }
1589 
1590 static uint32_t
1591 null_get_mac_address(void *arg, char *addr)
1592 {
1593 	spectral_ops_not_registered("get_mac_address");
1594 	return 0;
1595 }
1596 
1597 static uint32_t
1598 null_get_current_channel(void *arg)
1599 {
1600 	spectral_ops_not_registered("get_current_channel");
1601 	return 0;
1602 }
1603 
1604 static uint32_t
1605 null_reset_hw(void *arg)
1606 {
1607 	spectral_ops_not_registered("get_current_channel");
1608 	return 0;
1609 }
1610 
1611 static uint32_t
1612 null_get_chain_noise_floor(void *arg, int16_t *nf_buf)
1613 {
1614 	spectral_ops_not_registered("get_chain_noise_floor");
1615 	return 0;
1616 }
1617 
1618 static int
1619 null_spectral_process_phyerr(struct target_if_spectral *spectral,
1620 			     uint8_t *data,
1621 			     uint32_t datalen,
1622 			     struct target_if_spectral_rfqual_info *p_rfqual,
1623 			     struct target_if_spectral_chan_info *p_chaninfo,
1624 			     uint64_t tsf64,
1625 			     struct target_if_spectral_acs_stats *acs_stats)
1626 {
1627 	spectral_ops_not_registered("spectral_process_phyerr");
1628 	return 0;
1629 }
1630 
1631 static int
1632 null_process_spectral_report(struct wlan_objmgr_pdev *pdev,
1633 			     void *payload)
1634 {
1635 	spectral_ops_not_registered("process_spectral_report");
1636 	return 0;
1637 }
1638 /**
1639  * target_if_spectral_init_dummy_function_table() -
1640  * Initialize target_if internal
1641  * Spectral operations to dummy functions
1642  * @ps: Pointer to Spectral target_if internal private data
1643  *
1644  * Initialize all the function pointers in target_if_spectral_ops with
1645  * dummy functions.
1646  *
1647  * Return: None
1648  */
1649 static void
1650 target_if_spectral_init_dummy_function_table(struct target_if_spectral *ps)
1651 {
1652 	struct target_if_spectral_ops *p_sops = GET_TARGET_IF_SPECTRAL_OPS(ps);
1653 
1654 	p_sops->get_tsf64 = null_get_tsf64;
1655 	p_sops->get_capability = null_get_capability;
1656 	p_sops->set_rxfilter = null_set_rxfilter;
1657 	p_sops->get_rxfilter = null_get_rxfilter;
1658 	p_sops->is_spectral_enabled = null_is_spectral_enabled;
1659 	p_sops->is_spectral_active = null_is_spectral_active;
1660 	p_sops->start_spectral_scan = null_start_spectral_scan;
1661 	p_sops->stop_spectral_scan = null_stop_spectral_scan;
1662 	p_sops->get_extension_channel = null_get_extension_channel;
1663 	p_sops->get_ctl_noisefloor = null_get_ctl_noisefloor;
1664 	p_sops->get_ext_noisefloor = null_get_ext_noisefloor;
1665 	p_sops->configure_spectral = null_configure_spectral;
1666 	p_sops->get_spectral_config = null_get_spectral_config;
1667 	p_sops->get_ent_spectral_mask = null_get_ent_spectral_mask;
1668 	p_sops->get_mac_address = null_get_mac_address;
1669 	p_sops->get_current_channel = null_get_current_channel;
1670 	p_sops->reset_hw = null_reset_hw;
1671 	p_sops->get_chain_noise_floor = null_get_chain_noise_floor;
1672 	p_sops->spectral_process_phyerr = null_spectral_process_phyerr;
1673 	p_sops->process_spectral_report = null_process_spectral_report;
1674 }
1675 
1676 /**
1677  * target_if_spectral_register_funcs() - Initialize target_if internal Spectral
1678  * operations
1679  * @spectral: Pointer to Spectral target_if internal private data
1680  * @p: Pointer to Spectral function table
1681  *
1682  * Return: None
1683  */
1684 static void
1685 target_if_spectral_register_funcs(struct target_if_spectral *spectral,
1686 				  struct target_if_spectral_ops *p)
1687 {
1688 	struct target_if_spectral_ops *p_sops =
1689 		GET_TARGET_IF_SPECTRAL_OPS(spectral);
1690 
1691 	p_sops->get_tsf64 = p->get_tsf64;
1692 	p_sops->get_capability = p->get_capability;
1693 	p_sops->set_rxfilter = p->set_rxfilter;
1694 	p_sops->get_rxfilter = p->get_rxfilter;
1695 	p_sops->is_spectral_enabled = p->is_spectral_enabled;
1696 	p_sops->is_spectral_active = p->is_spectral_active;
1697 	p_sops->start_spectral_scan = p->start_spectral_scan;
1698 	p_sops->stop_spectral_scan = p->stop_spectral_scan;
1699 	p_sops->get_extension_channel = p->get_extension_channel;
1700 	p_sops->get_ctl_noisefloor = p->get_ctl_noisefloor;
1701 	p_sops->get_ext_noisefloor = p->get_ext_noisefloor;
1702 	p_sops->configure_spectral = p->configure_spectral;
1703 	p_sops->get_spectral_config = p->get_spectral_config;
1704 	p_sops->get_ent_spectral_mask = p->get_ent_spectral_mask;
1705 	p_sops->get_mac_address = p->get_mac_address;
1706 	p_sops->get_current_channel = p->get_current_channel;
1707 	p_sops->reset_hw = p->reset_hw;
1708 	p_sops->get_chain_noise_floor = p->get_chain_noise_floor;
1709 	p_sops->spectral_process_phyerr = p->spectral_process_phyerr;
1710 	p_sops->process_spectral_report = p->process_spectral_report;
1711 }
1712 
1713 /**
1714  * target_if_spectral_clear_stats() - Clear Spectral stats
1715  * @spectral: Pointer to Spectral target_if internal private data
1716  *
1717  * Function to clear spectral stats
1718  *
1719  * Return: None
1720  */
1721 static void
1722 target_if_spectral_clear_stats(struct target_if_spectral *spectral)
1723 {
1724 	struct target_if_spectral_ops *p_sops =
1725 		GET_TARGET_IF_SPECTRAL_OPS(spectral);
1726 
1727 	qdf_mem_zero(&spectral->spectral_stats,
1728 		     sizeof(struct target_if_spectral_stats));
1729 	spectral->spectral_stats.last_reset_tstamp =
1730 	    p_sops->get_tsf64(spectral);
1731 }
1732 
1733 /**
1734  * target_if_spectral_check_hw_capability() - Check whether HW supports spectral
1735  * @spectral: Pointer to Spectral target_if internal private data
1736  *
1737  * Function to check whether hardware supports spectral
1738  *
1739  * Return: True if HW supports Spectral, false if HW does not support Spectral
1740  */
1741 static int
1742 target_if_spectral_check_hw_capability(struct target_if_spectral *spectral)
1743 {
1744 	struct target_if_spectral_ops *p_sops = NULL;
1745 	struct spectral_caps *pcap = NULL;
1746 	int is_spectral_supported = true;
1747 
1748 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
1749 	pcap = &spectral->capability;
1750 
1751 	if (p_sops->get_capability(spectral, SPECTRAL_CAP_PHYDIAG) == false) {
1752 		is_spectral_supported = false;
1753 		spectral_info("SPECTRAL : No PHYDIAG support");
1754 		return is_spectral_supported;
1755 	}
1756 	pcap->phydiag_cap = 1;
1757 
1758 	if (p_sops->get_capability(spectral, SPECTRAL_CAP_RADAR) == false) {
1759 		is_spectral_supported = false;
1760 		spectral_info("SPECTRAL : No RADAR support");
1761 		return is_spectral_supported;
1762 	}
1763 	pcap->radar_cap = 1;
1764 
1765 	if (p_sops->get_capability(spectral,
1766 				   SPECTRAL_CAP_SPECTRAL_SCAN) == false) {
1767 		is_spectral_supported = false;
1768 		spectral_info("SPECTRAL : No SPECTRAL SUPPORT");
1769 		return is_spectral_supported;
1770 	}
1771 	pcap->spectral_cap = 1;
1772 
1773 	if (p_sops->get_capability(spectral, SPECTRAL_CAP_ADVNCD_SPECTRAL_SCAN)
1774 	    == false) {
1775 		spectral_info("SPECTRAL : No ADVANCED SPECTRAL SUPPORT");
1776 	} else {
1777 		pcap->advncd_spectral_cap = 1;
1778 	}
1779 
1780 	return is_spectral_supported;
1781 }
1782 
1783 /**
1784  * target_if_spectral_init_param_defaults() - Initialize Spectral
1785  * parameter defaults
1786  * @spectral: Pointer to Spectral target_if internal private data
1787  *
1788  * It is the caller's responsibility to ensure that the Spectral parameters
1789  * structure passed as part of Spectral target_if internal private data is
1790  * valid.
1791  *
1792  * Return: None
1793  */
1794 static void
1795 target_if_spectral_init_param_defaults(struct target_if_spectral *spectral)
1796 {
1797 	struct spectral_config *params = &spectral->params;
1798 
1799 	params->ss_count = SPECTRAL_SCAN_COUNT_DEFAULT;
1800 	params->ss_period = SPECTRAL_SCAN_PERIOD_DEFAULT;
1801 	params->ss_spectral_pri = SPECTRAL_SCAN_PRIORITY_DEFAULT;
1802 	params->ss_fft_size = SPECTRAL_SCAN_FFT_SIZE_DEFAULT;
1803 	params->ss_gc_ena = SPECTRAL_SCAN_GC_ENA_DEFAULT;
1804 	params->ss_restart_ena = SPECTRAL_SCAN_RESTART_ENA_DEFAULT;
1805 	params->ss_noise_floor_ref = SPECTRAL_SCAN_NOISE_FLOOR_REF_DEFAULT;
1806 	params->ss_init_delay = SPECTRAL_SCAN_INIT_DELAY_DEFAULT;
1807 	params->ss_nb_tone_thr = SPECTRAL_SCAN_NB_TONE_THR_DEFAULT;
1808 	params->ss_str_bin_thr = SPECTRAL_SCAN_STR_BIN_THR_DEFAULT;
1809 	params->ss_wb_rpt_mode = SPECTRAL_SCAN_WB_RPT_MODE_DEFAULT;
1810 	params->ss_rssi_rpt_mode = SPECTRAL_SCAN_RSSI_RPT_MODE_DEFAULT;
1811 	params->ss_rssi_thr = SPECTRAL_SCAN_RSSI_THR_DEFAULT;
1812 	params->ss_pwr_format = SPECTRAL_SCAN_PWR_FORMAT_DEFAULT;
1813 	params->ss_rpt_mode = SPECTRAL_SCAN_RPT_MODE_DEFAULT;
1814 	params->ss_bin_scale = SPECTRAL_SCAN_BIN_SCALE_DEFAULT;
1815 	params->ss_dbm_adj = SPECTRAL_SCAN_DBM_ADJ_DEFAULT;
1816 	/*
1817 	 * XXX
1818 	 * SPECTRAL_SCAN_CHN_MASK_DEFAULT (0x1) specifies that chain 0 is to be
1819 	 * used
1820 	 * for Spectral. This is expected to be an optimal configuration for
1821 	 * most chipsets considering aspects like power save. But this can later
1822 	 * optionally be changed to be set to the default system Rx chainmask
1823 	 * advertised by FW (if required for some purpose), once the Convergence
1824 	 * framework supports such retrieval at pdev attach time.
1825 	 */
1826 	params->ss_chn_mask = SPECTRAL_SCAN_CHN_MASK_DEFAULT;
1827 	params->ss_short_report = SPECTRAL_SCAN_SHORT_REPORT_DEFAULT;
1828 	params->ss_fft_period = SPECTRAL_SCAN_FFT_PERIOD_DEFAULT;
1829 }
1830 
1831 #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION
1832 /**
1833  * target_if_spectral_detach_simulation() - De-initialize Spectral
1834  * Simulation functionality
1835  * @spectral: Pointer to Spectral target_if internal private data
1836  *
1837  * Function to de-initialize Spectral Simulation functionality
1838  *
1839  * Return: None
1840  */
1841 static void
1842 target_if_spectral_detach_simulation(struct target_if_spectral *spectral)
1843 {
1844 	target_if_spectral_sim_detach(spectral);
1845 }
1846 
1847 #else
1848 static void
1849 target_if_spectral_detach_simulation(struct target_if_spectral *spectral)
1850 {
1851 }
1852 #endif
1853 
1854 /**
1855  * target_if_spectral_detach() - De-initialize target_if Spectral
1856  * @pdev: Pointer to pdev object
1857  *
1858  * Function to detach target_if spectral
1859  *
1860  * Return: None
1861  */
1862 static void
1863 target_if_spectral_detach(struct target_if_spectral *spectral)
1864 {
1865 	spectral_info("spectral detach");
1866 
1867 	if (spectral) {
1868 		qdf_spinlock_destroy(&spectral->param_info.osps_lock);
1869 
1870 		target_if_spectral_detach_simulation(spectral);
1871 
1872 		qdf_spinlock_destroy(&spectral->spectral_lock);
1873 		qdf_spinlock_destroy(&spectral->noise_pwr_reports_lock);
1874 
1875 		qdf_mem_free(spectral);
1876 		spectral = NULL;
1877 	}
1878 }
1879 
1880 #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION
1881 /**
1882  * target_if_spectral_attach_simulation() - Initialize Spectral Simulation
1883  * functionality
1884  * @spectral: Pointer to Spectral target_if internal private data
1885  *
1886  * Function to initialize spectral simulation functionality
1887  *
1888  * Return: 0 on success, negative error code on failure
1889  */
1890 static int
1891 target_if_spectral_attach_simulation(struct target_if_spectral *spectral)
1892 {
1893 	if (target_if_spectral_sim_attach(spectral)) {
1894 		qdf_mem_free(spectral);
1895 		return -EPERM;
1896 	}
1897 	return 0;
1898 }
1899 
1900 #else
1901 static int
1902 target_if_spectral_attach_simulation(struct target_if_spectral *spectral)
1903 {
1904 	return 0;
1905 }
1906 #endif
1907 
1908 /**
1909  * target_if_pdev_spectral_init() - Initialize target_if Spectral
1910  * functionality for the given pdev
1911  * @pdev: Pointer to pdev object
1912  *
1913  * Function to initialize pointer to spectral target_if internal private data
1914  *
1915  * Return: On success, pointer to Spectral target_if internal private data, on
1916  * failure, NULL
1917  */
1918 void *
1919 target_if_pdev_spectral_init(struct wlan_objmgr_pdev *pdev)
1920 {
1921 	struct target_if_spectral_ops *p_sops = NULL;
1922 	struct target_if_spectral *spectral = NULL;
1923 #ifdef CONFIG_WIN
1924 	uint32_t target_type;
1925 	uint32_t target_revision;
1926 	struct wlan_objmgr_psoc *psoc;
1927 	struct wlan_lmac_if_target_tx_ops *tx_ops;
1928 #endif
1929 
1930 	if (!pdev) {
1931 		spectral_err("SPECTRAL: pdev is NULL!");
1932 		return NULL;
1933 	}
1934 	spectral = (struct target_if_spectral *)qdf_mem_malloc(
1935 			sizeof(struct target_if_spectral));
1936 	if (!spectral) {
1937 		spectral_err("SPECTRAL : Memory allocation failed");
1938 		return spectral;
1939 	}
1940 	qdf_mem_zero(spectral, sizeof(struct target_if_spectral));
1941 	/* Store pdev in Spectral */
1942 	spectral->pdev_obj = pdev;
1943 
1944 #ifdef CONFIG_WIN
1945 	psoc = wlan_pdev_get_psoc(pdev);
1946 
1947 	tx_ops = &psoc->soc_cb.tx_ops.target_tx_ops;
1948 
1949 	if (tx_ops->tgt_get_tgt_type) {
1950 		target_type = tx_ops->tgt_get_tgt_type(psoc);
1951 	} else {
1952 		qdf_mem_free(spectral);
1953 		return NULL;
1954 	}
1955 
1956 	if (tx_ops->tgt_get_tgt_revision) {
1957 		target_revision = tx_ops->tgt_get_tgt_revision(psoc);
1958 	} else {
1959 		qdf_mem_free(spectral);
1960 		return NULL;
1961 	}
1962 #endif
1963 
1964 	/* init the function ptr table */
1965 	target_if_spectral_init_dummy_function_table(spectral);
1966 
1967 	/* get spectral function table */
1968 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
1969 	/* TODO : Should this be called here of after ath_attach ? */
1970 	if (p_sops->get_capability(spectral, SPECTRAL_CAP_PHYDIAG))
1971 		spectral_info("HAL_CAP_PHYDIAG : Capable");
1972 
1973 	/* TODO: Need to fix the capablity check for RADAR */
1974 	if (p_sops->get_capability(spectral, SPECTRAL_CAP_RADAR))
1975 		spectral_info("HAL_CAP_RADAR   : Capable");
1976 
1977 	/* TODO : Need to fix the capablity check for SPECTRAL */
1978 	/* TODO : Should this be called here of after ath_attach ? */
1979 	if (p_sops->get_capability(spectral, SPECTRAL_CAP_SPECTRAL_SCAN))
1980 		spectral_info("HAL_CAP_SPECTRAL_SCAN : Capable");
1981 
1982 	qdf_spinlock_create(&spectral->spectral_lock);
1983 	qdf_spinlock_create(&spectral->noise_pwr_reports_lock);
1984 	target_if_spectral_clear_stats(spectral);
1985 
1986 	/* Set the default values for spectral parameters */
1987 	target_if_spectral_init_param_defaults(spectral);
1988 #ifdef CONFIG_WIN
1989 	if (target_type == TARGET_TYPE_QCA8074) {
1990 		spectral->fftbin_size_war = 1;
1991 		spectral->inband_fftbin_size_adj = 1;
1992 	} else {
1993 		spectral->fftbin_size_war = 0;
1994 		spectral->inband_fftbin_size_adj = 0;
1995 	}
1996 	if ((target_type == TARGET_TYPE_QCA8074) || (
1997 		target_type == TARGET_TYPE_QCA6290)) {
1998 		spectral->spectral_gen = SPECTRAL_GEN3;
1999 		spectral->hdr_sig_exp = SPECTRAL_PHYERR_SIGNATURE_GEN3;
2000 		spectral->tag_sscan_summary_exp =
2001 		    TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN3;
2002 		spectral->tag_sscan_fft_exp = TLV_TAG_SEARCH_FFT_REPORT_GEN3;
2003 		spectral->tlvhdr_size = SPECTRAL_PHYERR_TLVSIZE_GEN3;
2004 	} else
2005 #endif
2006 	{
2007 		spectral->spectral_gen = SPECTRAL_GEN2;
2008 		spectral->hdr_sig_exp = SPECTRAL_PHYERR_SIGNATURE_GEN2;
2009 		spectral->tag_sscan_summary_exp =
2010 		    TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN2;
2011 		spectral->tag_sscan_fft_exp = TLV_TAG_SEARCH_FFT_REPORT_GEN2;
2012 		spectral->tlvhdr_size = sizeof(struct spectral_phyerr_tlv_gen2);
2013 	}
2014 
2015 	if (target_if_spectral_attach_simulation(spectral) < 0)
2016 		return NULL;
2017 
2018 	target_if_init_spectral_ops(spectral);
2019 
2020 	qdf_spinlock_create(&spectral->param_info.osps_lock);
2021 	spectral->param_info.osps_cache.osc_is_valid = 0;
2022 
2023 	target_if_spectral_register_funcs(spectral, &spectral_ops);
2024 
2025 	if (target_if_spectral_check_hw_capability(spectral) == false) {
2026 		target_if_spectral_detach(spectral);
2027 		spectral = NULL;
2028 	} else {
2029 		/*
2030 		 * TODO: Once the driver architecture transitions to chipset
2031 		 * versioning based checks, reflect this here.
2032 		 */
2033 		spectral->is_160_format = false;
2034 		spectral->is_lb_edge_extrabins_format = false;
2035 		spectral->is_rb_edge_extrabins_format = false;
2036 #ifdef CONFIG_WIN
2037 
2038 		if (target_type == TARGET_TYPE_QCA9984 ||
2039 		    target_type == TARGET_TYPE_QCA9888) {
2040 			spectral->is_160_format = true;
2041 			spectral->is_lb_edge_extrabins_format = true;
2042 			spectral->is_rb_edge_extrabins_format = true;
2043 		} else  if ((target_type == TARGET_TYPE_AR900B) &&
2044 			    (target_revision == AR900B_REV_2)) {
2045 			spectral->is_rb_edge_extrabins_format = true;
2046 		}
2047 
2048 		if (target_type == TARGET_TYPE_QCA9984 ||
2049 		    target_type == TARGET_TYPE_QCA9888)
2050 			spectral->is_sec80_rssi_war_required = true;
2051 		spectral->use_nl_bcast = true;
2052 #else
2053 		spectral->use_nl_bcast = false;
2054 #endif
2055 	}
2056 
2057 	return spectral;
2058 }
2059 
2060 /**
2061  * target_if_pdev_spectral_deinit() - De-initialize target_if Spectral
2062  * functionality for the given pdev
2063  * @pdev: Pointer to pdev object
2064  *
2065  * Function to de-initialize pointer to spectral target_if internal private data
2066  *
2067  * Return: None
2068  */
2069 void
2070 target_if_pdev_spectral_deinit(struct wlan_objmgr_pdev *pdev)
2071 {
2072 	struct target_if_spectral *spectral = NULL;
2073 
2074 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2075 	if (!spectral) {
2076 		spectral_err("SPECTRAL : Module doesn't exist");
2077 		return;
2078 	}
2079 	target_if_spectral_detach(spectral);
2080 
2081 	return;
2082 }
2083 
2084 /**
2085  * target_if_set_spectral_config() - Set spectral config
2086  * @pdev:       Pointer to pdev object
2087  * @threshtype: config type
2088  * @value:      config value
2089  *
2090  * API to set spectral configurations
2091  *
2092  * Return: 0 on success else failure
2093  */
2094 int
2095 target_if_set_spectral_config(struct wlan_objmgr_pdev *pdev,
2096 			      const uint32_t threshtype, const uint32_t value)
2097 {
2098 	struct spectral_config params;
2099 	struct target_if_spectral_ops *p_sops = NULL;
2100 	struct target_if_spectral *spectral = NULL;
2101 
2102 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2103 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
2104 	if (!spectral) {
2105 		spectral_err("spectral object is NULL");
2106 		return -EPERM;
2107 	}
2108 
2109 	switch (threshtype) {
2110 	case SPECTRAL_PARAM_FFT_PERIOD:
2111 		spectral->params.ss_fft_period = value;
2112 		break;
2113 	case SPECTRAL_PARAM_SCAN_PERIOD:
2114 		spectral->params.ss_period = value;
2115 		break;
2116 	case SPECTRAL_PARAM_SCAN_COUNT:
2117 		spectral->params.ss_count = value;
2118 		break;
2119 	case SPECTRAL_PARAM_SHORT_REPORT:
2120 		spectral->params.ss_short_report = (!!value) ? true : false;
2121 		break;
2122 	case SPECTRAL_PARAM_SPECT_PRI:
2123 		spectral->params.ss_spectral_pri = (!!value) ? true : false;
2124 		break;
2125 	case SPECTRAL_PARAM_FFT_SIZE:
2126 		spectral->params.ss_fft_size = value;
2127 		break;
2128 	case SPECTRAL_PARAM_GC_ENA:
2129 		spectral->params.ss_gc_ena = !!value;
2130 		break;
2131 	case SPECTRAL_PARAM_RESTART_ENA:
2132 		spectral->params.ss_restart_ena = !!value;
2133 		break;
2134 	case SPECTRAL_PARAM_NOISE_FLOOR_REF:
2135 		spectral->params.ss_noise_floor_ref = value;
2136 		break;
2137 	case SPECTRAL_PARAM_INIT_DELAY:
2138 		spectral->params.ss_init_delay = value;
2139 		break;
2140 	case SPECTRAL_PARAM_NB_TONE_THR:
2141 		spectral->params.ss_nb_tone_thr = value;
2142 		break;
2143 	case SPECTRAL_PARAM_STR_BIN_THR:
2144 		spectral->params.ss_str_bin_thr = value;
2145 		break;
2146 	case SPECTRAL_PARAM_WB_RPT_MODE:
2147 		spectral->params.ss_wb_rpt_mode = !!value;
2148 		break;
2149 	case SPECTRAL_PARAM_RSSI_RPT_MODE:
2150 		spectral->params.ss_rssi_rpt_mode = !!value;
2151 		break;
2152 	case SPECTRAL_PARAM_RSSI_THR:
2153 		spectral->params.ss_rssi_thr = value;
2154 		break;
2155 	case SPECTRAL_PARAM_PWR_FORMAT:
2156 		spectral->params.ss_pwr_format = !!value;
2157 		break;
2158 	case SPECTRAL_PARAM_RPT_MODE:
2159 		spectral->params.ss_rpt_mode = value;
2160 		break;
2161 	case SPECTRAL_PARAM_BIN_SCALE:
2162 		spectral->params.ss_bin_scale = value;
2163 		break;
2164 	case SPECTRAL_PARAM_DBM_ADJ:
2165 		spectral->params.ss_dbm_adj = !!value;
2166 		break;
2167 	case SPECTRAL_PARAM_CHN_MASK:
2168 		spectral->params.ss_chn_mask = value;
2169 		break;
2170 	}
2171 
2172 	p_sops->configure_spectral(spectral, &spectral->params);
2173 	/* only to validate the writes */
2174 	p_sops->get_spectral_config(spectral, &params);
2175 	return 0;
2176 }
2177 
2178 /**
2179  * target_if_get_fft_bin_count() - Get fft bin count for a given fft length
2180  * @fft_len: FFT length
2181  * @pdev: Pointer to pdev object
2182  *
2183  * API to get fft bin count for a given fft length
2184  *
2185  * Return: FFt bin count
2186  */
2187 static int
2188 target_if_get_fft_bin_count(int fft_len)
2189 {
2190 	int bin_count = 0;
2191 
2192 	switch (fft_len) {
2193 	case 5:
2194 		bin_count = 16;
2195 		break;
2196 	case 6:
2197 		bin_count = 32;
2198 		break;
2199 	case 7:
2200 		bin_count = 64;
2201 		break;
2202 	case 8:
2203 		bin_count = 128;
2204 		break;
2205 	case 9:
2206 		bin_count = 256;
2207 		break;
2208 	default:
2209 		break;
2210 	}
2211 
2212 	return bin_count;
2213 }
2214 
2215 /**
2216  * target_if_init_upper_lower_flags() - Initializes control and extension
2217  * segment flags
2218  * @fft_len: FFT length
2219  * @pdev: Pointer to pdev object
2220  *
2221  * API to initialize the control and extension flags with the lower/upper
2222  * segment based on the HT mode
2223  *
2224  * Return: FFt bin count
2225  */
2226 static void
2227 target_if_init_upper_lower_flags(struct target_if_spectral *spectral)
2228 {
2229 	int current_channel = 0;
2230 	int ext_channel = 0;
2231 	struct target_if_spectral_ops *p_sops =
2232 		GET_TARGET_IF_SPECTRAL_OPS(spectral);
2233 
2234 	current_channel = p_sops->get_current_channel(spectral);
2235 	ext_channel = p_sops->get_extension_channel(spectral);
2236 
2237 	if ((current_channel == 0) || (ext_channel == 0))
2238 		return;
2239 
2240 	if (spectral->sc_spectral_20_40_mode) {
2241 		/* HT40 mode */
2242 		if (ext_channel < current_channel) {
2243 			spectral->lower_is_extension = 1;
2244 			spectral->upper_is_control = 1;
2245 			spectral->lower_is_control = 0;
2246 			spectral->upper_is_extension = 0;
2247 		} else {
2248 			spectral->lower_is_extension = 0;
2249 			spectral->upper_is_control = 0;
2250 			spectral->lower_is_control = 1;
2251 			spectral->upper_is_extension = 1;
2252 		}
2253 	} else {
2254 		/* HT20 mode, lower is always control */
2255 		spectral->lower_is_extension = 0;
2256 		spectral->upper_is_control = 0;
2257 		spectral->lower_is_control = 1;
2258 		spectral->upper_is_extension = 0;
2259 	}
2260 }
2261 
2262 /**
2263  * target_if_get_spectral_config() - Get spectral configuration
2264  * @pdev: Pointer to pdev object
2265  * @param: Pointer to spectral_config structure in which the configuration
2266  * should be returned
2267  *
2268  * API to get the current spectral configuration
2269  *
2270  * Return: None
2271  */
2272 void
2273 target_if_get_spectral_config(struct wlan_objmgr_pdev *pdev,
2274 			      struct spectral_config *param)
2275 {
2276 	struct target_if_spectral_ops *p_sops = NULL;
2277 	struct target_if_spectral *spectral = NULL;
2278 
2279 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2280 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
2281 
2282 	qdf_mem_zero(param, sizeof(struct spectral_config));
2283 	p_sops->get_spectral_config(spectral, param);
2284 }
2285 
2286 /**
2287  * target_if_spectral_scan_enable_params() - Enable use of desired Spectral
2288  *                                           parameters
2289  * @spectral: Pointer to Spectral target_if internal private data
2290  * @spectral_params: Pointer to Spectral parameters
2291  *
2292  * Enable use of desired Spectral parameters by configuring them into HW, and
2293  * starting Spectral scan
2294  *
2295  * Return: 0 on success, 1 on failure
2296  */
2297 int
2298 target_if_spectral_scan_enable_params(struct target_if_spectral *spectral,
2299 				      struct spectral_config *spectral_params)
2300 {
2301 	int extension_channel = 0;
2302 	int current_channel = 0;
2303 	struct target_if_spectral_ops *p_sops = NULL;
2304 	struct wlan_objmgr_vdev *vdev = NULL;
2305 
2306 	if (!spectral) {
2307 		spectral_err("SPECTRAL : Spectral is NULL");
2308 		return 1;
2309 	}
2310 
2311 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
2312 
2313 	if (!p_sops) {
2314 		spectral_err("SPECTRAL : p_sops is NULL");
2315 		return 1;
2316 	}
2317 
2318 	spectral->sc_spectral_noise_pwr_cal =
2319 	    spectral_params->ss_spectral_pri ? 1 : 0;
2320 
2321 	/* check if extension channel is present */
2322 	extension_channel = p_sops->get_extension_channel(spectral);
2323 	current_channel = p_sops->get_current_channel(spectral);
2324 
2325 	vdev = target_if_spectral_get_vdev(spectral);
2326 	if (!vdev)
2327 		return 1;
2328 
2329 	spectral->ch_width = target_if_vdev_get_ch_width(vdev);
2330 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
2331 
2332 	if (spectral->ch_width == CH_WIDTH_INVALID)
2333 		return 1;
2334 
2335 	if (spectral->capability.advncd_spectral_cap) {
2336 		spectral->lb_edge_extrabins = 0;
2337 		spectral->rb_edge_extrabins = 0;
2338 
2339 		if (spectral->is_lb_edge_extrabins_format &&
2340 		    spectral->params.ss_rpt_mode == 2) {
2341 			spectral->lb_edge_extrabins = 4;
2342 		}
2343 
2344 		if (spectral->is_rb_edge_extrabins_format &&
2345 		    spectral->params.ss_rpt_mode == 2) {
2346 			spectral->rb_edge_extrabins = 4;
2347 		}
2348 
2349 		if (spectral->ch_width == CH_WIDTH_20MHZ) {
2350 			spectral->sc_spectral_20_40_mode = 0;
2351 
2352 			spectral->spectral_numbins =
2353 			    target_if_get_fft_bin_count(
2354 				spectral->params.ss_fft_size);
2355 			spectral->spectral_fft_len =
2356 			    target_if_get_fft_bin_count(
2357 				spectral->params.ss_fft_size);
2358 			spectral->spectral_data_len =
2359 			    target_if_get_fft_bin_count(
2360 				spectral->params.ss_fft_size);
2361 			/*
2362 			 * Initialize classifier params to be sent to user
2363 			 * space classifier
2364 			 */
2365 			spectral->classifier_params.lower_chan_in_mhz =
2366 			    current_channel;
2367 			spectral->classifier_params.upper_chan_in_mhz = 0;
2368 
2369 		} else if (spectral->ch_width == CH_WIDTH_40MHZ) {
2370 			/* TODO : Remove this variable */
2371 			spectral->sc_spectral_20_40_mode = 1;
2372 			spectral->spectral_numbins =
2373 			    target_if_get_fft_bin_count(
2374 				spectral->params.ss_fft_size);
2375 			spectral->spectral_fft_len =
2376 			    target_if_get_fft_bin_count(
2377 				spectral->params.ss_fft_size);
2378 			spectral->spectral_data_len =
2379 			    target_if_get_fft_bin_count(
2380 				spectral->params.ss_fft_size);
2381 
2382 			/*
2383 			 * Initialize classifier params to be sent to user
2384 			 * space classifier
2385 			 */
2386 			if (extension_channel < current_channel) {
2387 				spectral->classifier_params.lower_chan_in_mhz =
2388 				    extension_channel;
2389 				spectral->classifier_params.upper_chan_in_mhz =
2390 				    current_channel;
2391 			} else {
2392 				spectral->classifier_params.lower_chan_in_mhz =
2393 				    current_channel;
2394 				spectral->classifier_params.upper_chan_in_mhz =
2395 				    extension_channel;
2396 			}
2397 
2398 		} else if (spectral->ch_width == CH_WIDTH_80MHZ) {
2399 			/* Set the FFT Size */
2400 			/* TODO : Remove this variable */
2401 			spectral->sc_spectral_20_40_mode = 0;
2402 			spectral->spectral_numbins =
2403 			    target_if_get_fft_bin_count(
2404 				spectral->params.ss_fft_size);
2405 			spectral->spectral_fft_len =
2406 			    target_if_get_fft_bin_count(
2407 				spectral->params.ss_fft_size);
2408 			spectral->spectral_data_len =
2409 			    target_if_get_fft_bin_count(
2410 				spectral->params.ss_fft_size);
2411 
2412 			/*
2413 			 * Initialize classifier params to be sent to user
2414 			 * space classifier
2415 			 */
2416 			spectral->classifier_params.lower_chan_in_mhz =
2417 			    current_channel;
2418 			spectral->classifier_params.upper_chan_in_mhz = 0;
2419 
2420 			/*
2421 			 * Initialize classifier params to be sent to user
2422 			 * space classifier
2423 			 */
2424 			if (extension_channel < current_channel) {
2425 				spectral->classifier_params.lower_chan_in_mhz =
2426 				    extension_channel;
2427 				spectral->classifier_params.upper_chan_in_mhz =
2428 				    current_channel;
2429 			} else {
2430 				spectral->classifier_params.lower_chan_in_mhz =
2431 				    current_channel;
2432 				spectral->classifier_params.upper_chan_in_mhz =
2433 				    extension_channel;
2434 			}
2435 
2436 		} else if (spectral->ch_width == CH_WIDTH_160MHZ) {
2437 			/* Set the FFT Size */
2438 
2439 			/* The below applies to both 160 and 80+80 cases */
2440 
2441 			/* TODO : Remove this variable */
2442 			spectral->sc_spectral_20_40_mode = 0;
2443 			spectral->spectral_numbins =
2444 			    target_if_get_fft_bin_count(
2445 				spectral->params.ss_fft_size);
2446 			spectral->spectral_fft_len =
2447 			    target_if_get_fft_bin_count(
2448 				spectral->params.ss_fft_size);
2449 			spectral->spectral_data_len =
2450 			    target_if_get_fft_bin_count(
2451 				spectral->params.ss_fft_size);
2452 
2453 			/*
2454 			 * Initialize classifier params to be sent to user
2455 			 * space classifier
2456 			 */
2457 			spectral->classifier_params.lower_chan_in_mhz =
2458 			    current_channel;
2459 			spectral->classifier_params.upper_chan_in_mhz = 0;
2460 
2461 			/*
2462 			 * Initialize classifier params to be sent to user
2463 			 * space classifier
2464 			 */
2465 			if (extension_channel < current_channel) {
2466 				spectral->classifier_params.lower_chan_in_mhz =
2467 				    extension_channel;
2468 				spectral->classifier_params.upper_chan_in_mhz =
2469 				    current_channel;
2470 			} else {
2471 				spectral->classifier_params.lower_chan_in_mhz =
2472 				    current_channel;
2473 				spectral->classifier_params.upper_chan_in_mhz =
2474 				    extension_channel;
2475 			}
2476 		}
2477 
2478 		if (spectral->spectral_numbins) {
2479 			spectral->spectral_numbins +=
2480 			    spectral->lb_edge_extrabins;
2481 			spectral->spectral_numbins +=
2482 			    spectral->rb_edge_extrabins;
2483 		}
2484 
2485 		if (spectral->spectral_fft_len) {
2486 			spectral->spectral_fft_len +=
2487 			    spectral->lb_edge_extrabins;
2488 			spectral->spectral_fft_len +=
2489 			    spectral->rb_edge_extrabins;
2490 		}
2491 
2492 		if (spectral->spectral_data_len) {
2493 			spectral->spectral_data_len +=
2494 			    spectral->lb_edge_extrabins;
2495 			spectral->spectral_data_len +=
2496 			    spectral->rb_edge_extrabins;
2497 		}
2498 	} else {
2499 		/*
2500 		 * The decision to find 20/40 mode is found based on the
2501 		 * presence of extension channel
2502 		 * instead of channel width, as the channel width can
2503 		 * dynamically change
2504 		 */
2505 
2506 		if (extension_channel == 0) {
2507 			spectral->spectral_numbins = SPECTRAL_HT20_NUM_BINS;
2508 			spectral->spectral_dc_index = SPECTRAL_HT20_DC_INDEX;
2509 			spectral->spectral_fft_len = SPECTRAL_HT20_FFT_LEN;
2510 			spectral->spectral_data_len =
2511 			    SPECTRAL_HT20_TOTAL_DATA_LEN;
2512 			/* only valid in 20-40 mode */
2513 			spectral->spectral_lower_max_index_offset = -1;
2514 			/* only valid in 20-40 mode */
2515 			spectral->spectral_upper_max_index_offset = -1;
2516 			spectral->spectral_max_index_offset =
2517 			    spectral->spectral_fft_len + 2;
2518 			spectral->sc_spectral_20_40_mode = 0;
2519 
2520 			/*
2521 			 * Initialize classifier params to be sent to user
2522 			 * space classifier
2523 			 */
2524 			spectral->classifier_params.lower_chan_in_mhz =
2525 			    current_channel;
2526 			spectral->classifier_params.upper_chan_in_mhz = 0;
2527 
2528 		} else {
2529 			spectral->spectral_numbins =
2530 			    SPECTRAL_HT40_TOTAL_NUM_BINS;
2531 			spectral->spectral_fft_len = SPECTRAL_HT40_FFT_LEN;
2532 			spectral->spectral_data_len =
2533 			    SPECTRAL_HT40_TOTAL_DATA_LEN;
2534 			spectral->spectral_dc_index = SPECTRAL_HT40_DC_INDEX;
2535 			/* only valid in 20 mode */
2536 			spectral->spectral_max_index_offset = -1;
2537 			spectral->spectral_lower_max_index_offset =
2538 			    spectral->spectral_fft_len + 2;
2539 			spectral->spectral_upper_max_index_offset =
2540 			    spectral->spectral_fft_len + 5;
2541 			spectral->sc_spectral_20_40_mode = 1;
2542 
2543 			/*
2544 			 * Initialize classifier params to be sent to user
2545 			 * space classifier
2546 			 */
2547 			if (extension_channel < current_channel) {
2548 				spectral->classifier_params.lower_chan_in_mhz =
2549 				    extension_channel;
2550 				spectral->classifier_params.upper_chan_in_mhz =
2551 				    current_channel;
2552 			} else {
2553 				spectral->classifier_params.lower_chan_in_mhz =
2554 				    current_channel;
2555 				spectral->classifier_params.upper_chan_in_mhz =
2556 				    extension_channel;
2557 			}
2558 		}
2559 	}
2560 
2561 	spectral->send_single_packet = 0;
2562 	spectral->classifier_params.spectral_20_40_mode =
2563 	    spectral->sc_spectral_20_40_mode;
2564 	spectral->classifier_params.spectral_dc_index =
2565 	    spectral->spectral_dc_index;
2566 	spectral->spectral_sent_msg = 0;
2567 	spectral->classify_scan = 0;
2568 	spectral->num_spectral_data = 0;
2569 
2570 	if (!p_sops->is_spectral_active(spectral)) {
2571 		p_sops->configure_spectral(spectral, spectral_params);
2572 		p_sops->start_spectral_scan(spectral);
2573 	} else {
2574 	}
2575 
2576 	/* get current spectral configuration */
2577 	p_sops->get_spectral_config(spectral, &spectral->params);
2578 
2579 	target_if_init_upper_lower_flags(spectral);
2580 
2581 	return 0;
2582 }
2583 
2584 /**
2585  * target_if_start_spectral_scan() - Start spectral scan
2586  * @pdev: Pointer to pdev object
2587  *
2588  * API to start spectral scan
2589  *
2590  * Return: 0 in case of success, -1 on failure
2591  */
2592 int
2593 target_if_start_spectral_scan(struct wlan_objmgr_pdev *pdev)
2594 {
2595 	struct target_if_spectral_ops *p_sops = NULL;
2596 	struct target_if_spectral *spectral = NULL;
2597 
2598 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2599 	if (!spectral) {
2600 		spectral_err("SPECTRAL : Spectral LMAC object is NUll");
2601 		return -EPERM;
2602 	}
2603 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
2604 
2605 	qdf_spin_lock(&spectral->spectral_lock);
2606 	target_if_spectral_scan_enable_params(spectral, &spectral->params);
2607 	qdf_spin_unlock(&spectral->spectral_lock);
2608 
2609 	return 0;
2610 }
2611 
2612 void
2613 target_if_stop_spectral_scan(struct wlan_objmgr_pdev *pdev)
2614 {
2615 	struct target_if_spectral_ops *p_sops = NULL;
2616 	struct target_if_spectral *spectral = NULL;
2617 
2618 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2619 	if (!spectral) {
2620 		spectral_err("SPECTRAL : Spectral LMAC object is NUll ");
2621 		return;
2622 	}
2623 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
2624 
2625 	qdf_spin_lock(&spectral->spectral_lock);
2626 	p_sops->stop_spectral_scan(spectral);
2627 	if (spectral->classify_scan) {
2628 		/* TODO : Check if this logic is necessary */
2629 		spectral->detects_control_channel = 0;
2630 		spectral->detects_extension_channel = 0;
2631 		spectral->detects_above_dc = 0;
2632 		spectral->detects_below_dc = 0;
2633 		spectral->classify_scan = 0;
2634 	}
2635 
2636 	spectral->send_single_packet = 0;
2637 	spectral->sc_spectral_scan = 0;
2638 	spectral->sc_spectral_noise_pwr_cal = 0;
2639 
2640 	/*
2641 	 * Reset the priority because it stops WLAN rx.
2642 	 * If it is needed to set, user has to set it explicitly
2643 	 *
2644 	 */
2645 	/* Reset Priority */
2646 	spectral->params.ss_spectral_pri = 0;
2647 	qdf_spin_unlock(&spectral->spectral_lock);
2648 }
2649 
2650 /**
2651  * target_if_is_spectral_active() - Get whether Spectral is active
2652  * @pdev: Pointer to pdev object
2653  *
2654  * API to get whether Spectral is active
2655  *
2656  * Return: True if Spectral is active, false if Spectral is not active
2657  */
2658 bool
2659 target_if_is_spectral_active(struct wlan_objmgr_pdev *pdev)
2660 {
2661 	struct target_if_spectral *spectral = NULL;
2662 	struct target_if_spectral_ops *p_sops = NULL;
2663 
2664 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2665 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
2666 	return p_sops->is_spectral_active(spectral);
2667 }
2668 
2669 /**
2670  * target_if_is_spectral_enabled() - Get whether Spectral is enabled
2671  * @pdev: Pointer to pdev object
2672  *
2673  * API to get whether Spectral is enabled
2674  *
2675  * Return: True if Spectral is enabled, false if Spectral is not enabled
2676  */
2677 bool
2678 target_if_is_spectral_enabled(struct wlan_objmgr_pdev *pdev)
2679 {
2680 	struct target_if_spectral *spectral = NULL;
2681 	struct target_if_spectral_ops *p_sops = NULL;
2682 
2683 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2684 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
2685 	return p_sops->is_spectral_enabled(spectral);
2686 }
2687 
2688 /**
2689  * target_if_set_debug_level() - Set debug level for Spectral
2690  * @pdev: Pointer to pdev object
2691  * @debug_level: Debug level
2692  *
2693  * API to set the debug level for Spectral
2694  *
2695  * Return: 0 in case of success
2696  */
2697 int
2698 target_if_set_debug_level(struct wlan_objmgr_pdev *pdev, uint32_t debug_level)
2699 {
2700 	spectral_debug_level = (DEBUG_SPECTRAL << debug_level);
2701 	return 0;
2702 }
2703 
2704 /**
2705  * target_if_get_debug_level() - Get debug level for Spectral
2706  * @pdev: Pointer to pdev object
2707  *
2708  * API to get the debug level for Spectral
2709  *
2710  * Return: Current debug level
2711  */
2712 uint32_t
2713 target_if_get_debug_level(struct wlan_objmgr_pdev *pdev)
2714 {
2715 	return spectral_debug_level;
2716 }
2717 
2718 /**
2719  * target_if_get_spectral_capinfo() - Get Spectral capability information
2720  * @pdev: Pointer to pdev object
2721  * @outdata: Buffer into which data should be copied
2722  *
2723  * API to get the spectral capability information
2724  *
2725  * Return: void
2726  */
2727 void
2728 target_if_get_spectral_capinfo(struct wlan_objmgr_pdev *pdev, void *outdata)
2729 {
2730 	struct target_if_spectral *spectral = NULL;
2731 
2732 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2733 	qdf_mem_copy(outdata, &spectral->capability,
2734 		     sizeof(struct spectral_caps));
2735 }
2736 
2737 /**
2738  * target_if_get_spectral_diagstats() - Get Spectral diagnostic statistics
2739  * @pdev:  Pointer to pdev object
2740  * @outdata: Buffer into which data should be copied
2741  *
2742  * API to get the spectral diagnostic statistics
2743  *
2744  * Return: void
2745  */
2746 void
2747 target_if_get_spectral_diagstats(struct wlan_objmgr_pdev *pdev, void *outdata)
2748 {
2749 	struct target_if_spectral *spectral = NULL;
2750 
2751 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2752 	qdf_mem_copy(outdata, &spectral->diag_stats,
2753 		     sizeof(struct spectral_diag_stats));
2754 }
2755 
2756 /**
2757  * target_if_register_wmi_spectral_cmd_ops() - Register wmi_spectral_cmd_ops
2758  * @cmd_ops: Pointer to the structure having wmi_spectral_cmd function pointers
2759  * @pdev: Pointer to pdev object
2760  *
2761  * API for register wmi_spectral_cmd_ops in spectral internal data structure
2762  *
2763  * Return: void
2764  */
2765 void
2766 target_if_register_wmi_spectral_cmd_ops(struct wlan_objmgr_pdev *pdev,
2767 					struct wmi_spectral_cmd_ops *cmd_ops)
2768 {
2769 	struct target_if_spectral *spectral = NULL;
2770 
2771 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2772 	spectral->param_wmi_cmd_ops.wmi_spectral_configure_cmd_send =
2773 	    cmd_ops->wmi_spectral_configure_cmd_send;
2774 	spectral->param_wmi_cmd_ops.wmi_spectral_enable_cmd_send =
2775 	    cmd_ops->wmi_spectral_enable_cmd_send;
2776 }
2777 
2778 /**
2779  * target_if_register_netlink_cb() - Register Netlink callbacks
2780  * @pdev: Pointer to pdev object
2781  * @nl_cb: Netlink callbacks to register
2782  *
2783  * Return: void
2784  */
2785 static void
2786 target_if_register_netlink_cb(
2787 	struct wlan_objmgr_pdev *pdev,
2788 	struct spectral_nl_cb *nl_cb)
2789 {
2790 	struct target_if_spectral *spectral = NULL;
2791 
2792 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2793 	qdf_mem_copy(&spectral->nl_cb, nl_cb, sizeof(struct spectral_nl_cb));
2794 
2795 	if (spectral->use_nl_bcast)
2796 		spectral->send_phy_data = spectral->nl_cb.send_nl_bcast;
2797 	else
2798 		spectral->send_phy_data = spectral->nl_cb.send_nl_unicast;
2799 }
2800 
2801 /**
2802  * target_if_use_nl_bcast() - Get whether to use broadcast/unicast while sending
2803  * Netlink messages to the application layer
2804  * @pdev: Pointer to pdev object
2805  *
2806  * Return: true for broadcast, false for unicast
2807  */
2808 static bool
2809 target_if_use_nl_bcast(struct wlan_objmgr_pdev *pdev)
2810 {
2811 	struct target_if_spectral *spectral = NULL;
2812 
2813 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2814 	return spectral->use_nl_bcast;
2815 }
2816 
2817 /**
2818  * target_if_deregister_netlink_cb() - De-register Netlink callbacks
2819  * @pdev: Pointer to pdev object
2820  *
2821  * Return: void
2822  */
2823 static void
2824 target_if_deregister_netlink_cb(struct wlan_objmgr_pdev *pdev)
2825 {
2826 	struct target_if_spectral *spectral = NULL;
2827 
2828 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2829 	if (!spectral) {
2830 		spectral_err("SPECTRAL : Module doesn't exist");
2831 		return;
2832 	}
2833 
2834 	qdf_mem_zero(&spectral->nl_cb, sizeof(struct spectral_nl_cb));
2835 }
2836 
2837 static int
2838 target_if_process_spectral_report(struct wlan_objmgr_pdev *pdev,
2839 				  void *payload)
2840 {
2841 	struct target_if_spectral *spectral = NULL;
2842 	struct target_if_spectral_ops *p_sops = NULL;
2843 
2844 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2845 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
2846 
2847 	return p_sops->process_spectral_report(pdev, payload);
2848 }
2849 
2850 void
2851 target_if_sptrl_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
2852 {
2853 	tx_ops->sptrl_tx_ops.sptrlto_pdev_spectral_init =
2854 	    target_if_pdev_spectral_init;
2855 	tx_ops->sptrl_tx_ops.sptrlto_pdev_spectral_deinit =
2856 	    target_if_pdev_spectral_deinit;
2857 	tx_ops->sptrl_tx_ops.sptrlto_set_spectral_config =
2858 	    target_if_set_spectral_config;
2859 	tx_ops->sptrl_tx_ops.sptrlto_get_spectral_config =
2860 	    target_if_get_spectral_config;
2861 	tx_ops->sptrl_tx_ops.sptrlto_start_spectral_scan =
2862 	    target_if_start_spectral_scan;
2863 	tx_ops->sptrl_tx_ops.sptrlto_stop_spectral_scan =
2864 	    target_if_stop_spectral_scan;
2865 	tx_ops->sptrl_tx_ops.sptrlto_is_spectral_active =
2866 	    target_if_is_spectral_active;
2867 	tx_ops->sptrl_tx_ops.sptrlto_is_spectral_enabled =
2868 	    target_if_is_spectral_enabled;
2869 	tx_ops->sptrl_tx_ops.sptrlto_set_debug_level =
2870 	    target_if_set_debug_level;
2871 	tx_ops->sptrl_tx_ops.sptrlto_get_debug_level =
2872 	    target_if_get_debug_level;
2873 	tx_ops->sptrl_tx_ops.sptrlto_get_spectral_capinfo =
2874 	    target_if_get_spectral_capinfo;
2875 	tx_ops->sptrl_tx_ops.sptrlto_get_spectral_diagstats =
2876 	    target_if_get_spectral_diagstats;
2877 	tx_ops->sptrl_tx_ops.sptrlto_register_wmi_spectral_cmd_ops =
2878 	    target_if_register_wmi_spectral_cmd_ops;
2879 	tx_ops->sptrl_tx_ops.sptrlto_register_netlink_cb =
2880 	    target_if_register_netlink_cb;
2881 	tx_ops->sptrl_tx_ops.sptrlto_use_nl_bcast =
2882 	    target_if_use_nl_bcast;
2883 	tx_ops->sptrl_tx_ops.sptrlto_deregister_netlink_cb =
2884 	    target_if_deregister_netlink_cb;
2885 	tx_ops->sptrl_tx_ops.sptrlto_process_spectral_report =
2886 		target_if_process_spectral_report;
2887 }
2888 qdf_export_symbol(target_if_sptrl_register_tx_ops);
2889 
2890 void
2891 target_if_spectral_send_intf_found_msg(struct wlan_objmgr_pdev *pdev,
2892 				       uint16_t cw_int, uint32_t dcs_enabled)
2893 {
2894 	struct spectral_samp_msg *msg = NULL;
2895 	struct target_if_spectral_ops *p_sops = NULL;
2896 	struct target_if_spectral *spectral = NULL;
2897 
2898 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2899 	msg  = (struct spectral_samp_msg *)spectral->nl_cb.get_nbuff(
2900 			spectral->pdev_obj);
2901 
2902 	if (msg) {
2903 		msg->int_type = cw_int ?
2904 		    SPECTRAL_DCS_INT_CW : SPECTRAL_DCS_INT_WIFI;
2905 		msg->dcs_enabled = dcs_enabled;
2906 		msg->signature = SPECTRAL_SIGNATURE;
2907 		p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
2908 		p_sops->get_mac_address(spectral, msg->macaddr);
2909 		if (spectral->send_phy_data(pdev) == 0)
2910 			spectral->spectral_sent_msg++;
2911 	}
2912 }
2913 qdf_export_symbol(target_if_spectral_send_intf_found_msg);
2914