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