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