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