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