xref: /wlan-dirver/qca-wifi-host-cmn/target_if/spectral/target_if_spectral.c (revision 27d564647e9b50e713c60b0d7e5ea2a9b0a3ae74)
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 		if (spectral->spectral_gen == SPECTRAL_GEN3)
1889 			deinit_160mhz_delivery_state_machine(spectral);
1890 		qdf_spinlock_destroy(&spectral->param_info.osps_lock);
1891 
1892 		target_if_spectral_detach_simulation(spectral);
1893 
1894 		qdf_spinlock_destroy(&spectral->spectral_lock);
1895 		qdf_spinlock_destroy(&spectral->noise_pwr_reports_lock);
1896 
1897 		qdf_mem_free(spectral);
1898 		spectral = NULL;
1899 	}
1900 }
1901 
1902 #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION
1903 /**
1904  * target_if_spectral_attach_simulation() - Initialize Spectral Simulation
1905  * functionality
1906  * @spectral: Pointer to Spectral target_if internal private data
1907  *
1908  * Function to initialize spectral simulation functionality
1909  *
1910  * Return: 0 on success, negative error code on failure
1911  */
1912 static int
1913 target_if_spectral_attach_simulation(struct target_if_spectral *spectral)
1914 {
1915 	if (target_if_spectral_sim_attach(spectral)) {
1916 		qdf_mem_free(spectral);
1917 		return -EPERM;
1918 	}
1919 	return 0;
1920 }
1921 
1922 #else
1923 static int
1924 target_if_spectral_attach_simulation(struct target_if_spectral *spectral)
1925 {
1926 	return 0;
1927 }
1928 #endif
1929 
1930 /**
1931  * target_if_pdev_spectral_init() - Initialize target_if Spectral
1932  * functionality for the given pdev
1933  * @pdev: Pointer to pdev object
1934  *
1935  * Function to initialize pointer to spectral target_if internal private data
1936  *
1937  * Return: On success, pointer to Spectral target_if internal private data, on
1938  * failure, NULL
1939  */
1940 void *
1941 target_if_pdev_spectral_init(struct wlan_objmgr_pdev *pdev)
1942 {
1943 	struct target_if_spectral_ops *p_sops = NULL;
1944 	struct target_if_spectral *spectral = NULL;
1945 #ifdef CONFIG_WIN
1946 	uint32_t target_type;
1947 	uint32_t target_revision;
1948 	struct wlan_objmgr_psoc *psoc;
1949 	struct wlan_lmac_if_target_tx_ops *tx_ops;
1950 #endif
1951 
1952 	if (!pdev) {
1953 		spectral_err("SPECTRAL: pdev is NULL!");
1954 		return NULL;
1955 	}
1956 	spectral = (struct target_if_spectral *)qdf_mem_malloc(
1957 			sizeof(struct target_if_spectral));
1958 	if (!spectral) {
1959 		spectral_err("SPECTRAL : Memory allocation failed");
1960 		return spectral;
1961 	}
1962 	qdf_mem_zero(spectral, sizeof(struct target_if_spectral));
1963 	/* Store pdev in Spectral */
1964 	spectral->pdev_obj = pdev;
1965 
1966 #ifdef CONFIG_WIN
1967 	psoc = wlan_pdev_get_psoc(pdev);
1968 
1969 	tx_ops = &psoc->soc_cb.tx_ops.target_tx_ops;
1970 
1971 	if (tx_ops->tgt_get_tgt_type) {
1972 		target_type = tx_ops->tgt_get_tgt_type(psoc);
1973 	} else {
1974 		qdf_mem_free(spectral);
1975 		return NULL;
1976 	}
1977 
1978 	if (tx_ops->tgt_get_tgt_revision) {
1979 		target_revision = tx_ops->tgt_get_tgt_revision(psoc);
1980 	} else {
1981 		qdf_mem_free(spectral);
1982 		return NULL;
1983 	}
1984 #endif
1985 
1986 	/* init the function ptr table */
1987 	target_if_spectral_init_dummy_function_table(spectral);
1988 
1989 	/* get spectral function table */
1990 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
1991 	/* TODO : Should this be called here of after ath_attach ? */
1992 	if (p_sops->get_capability(spectral, SPECTRAL_CAP_PHYDIAG))
1993 		spectral_info("HAL_CAP_PHYDIAG : Capable");
1994 
1995 	/* TODO: Need to fix the capablity check for RADAR */
1996 	if (p_sops->get_capability(spectral, SPECTRAL_CAP_RADAR))
1997 		spectral_info("HAL_CAP_RADAR   : Capable");
1998 
1999 	/* TODO : Need to fix the capablity check for SPECTRAL */
2000 	/* TODO : Should this be called here of after ath_attach ? */
2001 	if (p_sops->get_capability(spectral, SPECTRAL_CAP_SPECTRAL_SCAN))
2002 		spectral_info("HAL_CAP_SPECTRAL_SCAN : Capable");
2003 
2004 	qdf_spinlock_create(&spectral->spectral_lock);
2005 	qdf_spinlock_create(&spectral->noise_pwr_reports_lock);
2006 	target_if_spectral_clear_stats(spectral);
2007 
2008 #ifdef CONFIG_WIN
2009 	if ((target_type == TARGET_TYPE_QCA8074) ||
2010 	    (target_type == TARGET_TYPE_QCA8074V2)) {
2011 		spectral->fftbin_size_war = 1;
2012 		spectral->inband_fftbin_size_adj = 1;
2013 		spectral->null_fftbin_adj = 1;
2014 	} else {
2015 		spectral->fftbin_size_war = 0;
2016 		spectral->inband_fftbin_size_adj = 0;
2017 		spectral->null_fftbin_adj = 0;
2018 	}
2019 
2020 	if ((target_type == TARGET_TYPE_QCA8074) ||
2021 	    (target_type == TARGET_TYPE_QCA8074V2) ||
2022 	    (target_type == TARGET_TYPE_QCA6290)) {
2023 		spectral->spectral_gen = SPECTRAL_GEN3;
2024 		spectral->hdr_sig_exp = SPECTRAL_PHYERR_SIGNATURE_GEN3;
2025 		spectral->tag_sscan_summary_exp =
2026 		    TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN3;
2027 		spectral->tag_sscan_fft_exp = TLV_TAG_SEARCH_FFT_REPORT_GEN3;
2028 		spectral->tlvhdr_size = SPECTRAL_PHYERR_TLVSIZE_GEN3;
2029 	} else
2030 #endif
2031 	{
2032 		spectral->spectral_gen = SPECTRAL_GEN2;
2033 		spectral->hdr_sig_exp = SPECTRAL_PHYERR_SIGNATURE_GEN2;
2034 		spectral->tag_sscan_summary_exp =
2035 		    TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN2;
2036 		spectral->tag_sscan_fft_exp = TLV_TAG_SEARCH_FFT_REPORT_GEN2;
2037 		spectral->tlvhdr_size = sizeof(struct spectral_phyerr_tlv_gen2);
2038 	}
2039 
2040 	/* Set the default values for spectral parameters */
2041 	target_if_spectral_init_param_defaults(spectral);
2042 	/* Init spectral capability */
2043 	target_if_init_spectral_capability(spectral);
2044 	if (target_if_spectral_attach_simulation(spectral) < 0)
2045 		return NULL;
2046 
2047 	target_if_init_spectral_ops(spectral);
2048 
2049 	qdf_spinlock_create(&spectral->param_info.osps_lock);
2050 	spectral->param_info.osps_cache.osc_is_valid = 0;
2051 
2052 	target_if_spectral_register_funcs(spectral, &spectral_ops);
2053 
2054 	if (target_if_spectral_check_hw_capability(spectral) == false) {
2055 		target_if_spectral_detach(spectral);
2056 		spectral = NULL;
2057 	} else {
2058 		/*
2059 		 * TODO: Once the driver architecture transitions to chipset
2060 		 * versioning based checks, reflect this here.
2061 		 */
2062 		spectral->is_160_format = false;
2063 		spectral->is_lb_edge_extrabins_format = false;
2064 		spectral->is_rb_edge_extrabins_format = false;
2065 #ifdef CONFIG_WIN
2066 
2067 		if (target_type == TARGET_TYPE_QCA9984 ||
2068 		    target_type == TARGET_TYPE_QCA9888) {
2069 			spectral->is_160_format = true;
2070 			spectral->is_lb_edge_extrabins_format = true;
2071 			spectral->is_rb_edge_extrabins_format = true;
2072 		} else  if ((target_type == TARGET_TYPE_AR900B) &&
2073 			    (target_revision == AR900B_REV_2)) {
2074 			spectral->is_rb_edge_extrabins_format = true;
2075 		}
2076 
2077 		if (target_type == TARGET_TYPE_QCA9984 ||
2078 		    target_type == TARGET_TYPE_QCA9888)
2079 			spectral->is_sec80_rssi_war_required = true;
2080 		spectral->use_nl_bcast = true;
2081 #else
2082 		spectral->use_nl_bcast = false;
2083 #endif
2084 		if (spectral->spectral_gen == SPECTRAL_GEN3)
2085 			init_160mhz_delivery_state_machine(spectral);
2086 	}
2087 
2088 	return spectral;
2089 }
2090 
2091 /**
2092  * target_if_pdev_spectral_deinit() - De-initialize target_if Spectral
2093  * functionality for the given pdev
2094  * @pdev: Pointer to pdev object
2095  *
2096  * Function to de-initialize pointer to spectral target_if internal private data
2097  *
2098  * Return: None
2099  */
2100 void
2101 target_if_pdev_spectral_deinit(struct wlan_objmgr_pdev *pdev)
2102 {
2103 	struct target_if_spectral *spectral = NULL;
2104 
2105 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2106 	if (!spectral) {
2107 		spectral_err("SPECTRAL : Module doesn't exist");
2108 		return;
2109 	}
2110 	target_if_spectral_detach(spectral);
2111 
2112 	return;
2113 }
2114 
2115 /**
2116  * target_if_set_spectral_config() - Set spectral config
2117  * @pdev:       Pointer to pdev object
2118  * @threshtype: config type
2119  * @value:      config value
2120  *
2121  * API to set spectral configurations
2122  *
2123  * Return: 0 on success else failure
2124  */
2125 int
2126 target_if_set_spectral_config(struct wlan_objmgr_pdev *pdev,
2127 			      const uint32_t threshtype, const uint32_t value)
2128 {
2129 	struct spectral_config params;
2130 	struct target_if_spectral_ops *p_sops = NULL;
2131 	struct target_if_spectral *spectral = NULL;
2132 
2133 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2134 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
2135 	if (!spectral) {
2136 		spectral_err("spectral object is NULL");
2137 		return -EPERM;
2138 	}
2139 
2140 	switch (threshtype) {
2141 	case SPECTRAL_PARAM_FFT_PERIOD:
2142 		spectral->params.ss_fft_period = value;
2143 		break;
2144 	case SPECTRAL_PARAM_SCAN_PERIOD:
2145 		spectral->params.ss_period = value;
2146 		break;
2147 	case SPECTRAL_PARAM_SCAN_COUNT:
2148 		spectral->params.ss_count = value;
2149 		break;
2150 	case SPECTRAL_PARAM_SHORT_REPORT:
2151 		spectral->params.ss_short_report = (!!value) ? true : false;
2152 		break;
2153 	case SPECTRAL_PARAM_SPECT_PRI:
2154 		spectral->params.ss_spectral_pri = (!!value) ? true : false;
2155 		break;
2156 	case SPECTRAL_PARAM_FFT_SIZE:
2157 		spectral->params.ss_fft_size = value;
2158 		break;
2159 	case SPECTRAL_PARAM_GC_ENA:
2160 		spectral->params.ss_gc_ena = !!value;
2161 		break;
2162 	case SPECTRAL_PARAM_RESTART_ENA:
2163 		spectral->params.ss_restart_ena = !!value;
2164 		break;
2165 	case SPECTRAL_PARAM_NOISE_FLOOR_REF:
2166 		spectral->params.ss_noise_floor_ref = value;
2167 		break;
2168 	case SPECTRAL_PARAM_INIT_DELAY:
2169 		spectral->params.ss_init_delay = value;
2170 		break;
2171 	case SPECTRAL_PARAM_NB_TONE_THR:
2172 		spectral->params.ss_nb_tone_thr = value;
2173 		break;
2174 	case SPECTRAL_PARAM_STR_BIN_THR:
2175 		spectral->params.ss_str_bin_thr = value;
2176 		break;
2177 	case SPECTRAL_PARAM_WB_RPT_MODE:
2178 		spectral->params.ss_wb_rpt_mode = !!value;
2179 		break;
2180 	case SPECTRAL_PARAM_RSSI_RPT_MODE:
2181 		spectral->params.ss_rssi_rpt_mode = !!value;
2182 		break;
2183 	case SPECTRAL_PARAM_RSSI_THR:
2184 		spectral->params.ss_rssi_thr = value;
2185 		break;
2186 	case SPECTRAL_PARAM_PWR_FORMAT:
2187 		spectral->params.ss_pwr_format = !!value;
2188 		break;
2189 	case SPECTRAL_PARAM_RPT_MODE:
2190 		spectral->params.ss_rpt_mode = value;
2191 		break;
2192 	case SPECTRAL_PARAM_BIN_SCALE:
2193 		spectral->params.ss_bin_scale = value;
2194 		break;
2195 	case SPECTRAL_PARAM_DBM_ADJ:
2196 		spectral->params.ss_dbm_adj = !!value;
2197 		break;
2198 	case SPECTRAL_PARAM_CHN_MASK:
2199 		spectral->params.ss_chn_mask = value;
2200 		break;
2201 	}
2202 
2203 	p_sops->configure_spectral(spectral, &spectral->params);
2204 	/* only to validate the writes */
2205 	p_sops->get_spectral_config(spectral, &params);
2206 	return 0;
2207 }
2208 
2209 /**
2210  * target_if_get_fft_bin_count() - Get fft bin count for a given fft length
2211  * @fft_len: FFT length
2212  * @pdev: Pointer to pdev object
2213  *
2214  * API to get fft bin count for a given fft length
2215  *
2216  * Return: FFt bin count
2217  */
2218 static int
2219 target_if_get_fft_bin_count(int fft_len)
2220 {
2221 	int bin_count = 0;
2222 
2223 	switch (fft_len) {
2224 	case 5:
2225 		bin_count = 16;
2226 		break;
2227 	case 6:
2228 		bin_count = 32;
2229 		break;
2230 	case 7:
2231 		bin_count = 64;
2232 		break;
2233 	case 8:
2234 		bin_count = 128;
2235 		break;
2236 	case 9:
2237 		bin_count = 256;
2238 		break;
2239 	default:
2240 		break;
2241 	}
2242 
2243 	return bin_count;
2244 }
2245 
2246 /**
2247  * target_if_init_upper_lower_flags() - Initializes control and extension
2248  * segment flags
2249  * @fft_len: FFT length
2250  * @pdev: Pointer to pdev object
2251  *
2252  * API to initialize the control and extension flags with the lower/upper
2253  * segment based on the HT mode
2254  *
2255  * Return: FFt bin count
2256  */
2257 static void
2258 target_if_init_upper_lower_flags(struct target_if_spectral *spectral)
2259 {
2260 	int current_channel = 0;
2261 	int ext_channel = 0;
2262 	struct target_if_spectral_ops *p_sops =
2263 		GET_TARGET_IF_SPECTRAL_OPS(spectral);
2264 
2265 	current_channel = p_sops->get_current_channel(spectral);
2266 	ext_channel = p_sops->get_extension_channel(spectral);
2267 
2268 	if ((current_channel == 0) || (ext_channel == 0))
2269 		return;
2270 
2271 	if (spectral->sc_spectral_20_40_mode) {
2272 		/* HT40 mode */
2273 		if (ext_channel < current_channel) {
2274 			spectral->lower_is_extension = 1;
2275 			spectral->upper_is_control = 1;
2276 			spectral->lower_is_control = 0;
2277 			spectral->upper_is_extension = 0;
2278 		} else {
2279 			spectral->lower_is_extension = 0;
2280 			spectral->upper_is_control = 0;
2281 			spectral->lower_is_control = 1;
2282 			spectral->upper_is_extension = 1;
2283 		}
2284 	} else {
2285 		/* HT20 mode, lower is always control */
2286 		spectral->lower_is_extension = 0;
2287 		spectral->upper_is_control = 0;
2288 		spectral->lower_is_control = 1;
2289 		spectral->upper_is_extension = 0;
2290 	}
2291 }
2292 
2293 /**
2294  * target_if_get_spectral_config() - Get spectral configuration
2295  * @pdev: Pointer to pdev object
2296  * @param: Pointer to spectral_config structure in which the configuration
2297  * should be returned
2298  *
2299  * API to get the current spectral configuration
2300  *
2301  * Return: None
2302  */
2303 void
2304 target_if_get_spectral_config(struct wlan_objmgr_pdev *pdev,
2305 			      struct spectral_config *param)
2306 {
2307 	struct target_if_spectral_ops *p_sops = NULL;
2308 	struct target_if_spectral *spectral = NULL;
2309 
2310 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2311 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
2312 
2313 	qdf_mem_zero(param, sizeof(struct spectral_config));
2314 	p_sops->get_spectral_config(spectral, param);
2315 }
2316 
2317 /**
2318  * target_if_spectral_scan_enable_params() - Enable use of desired Spectral
2319  *                                           parameters
2320  * @spectral: Pointer to Spectral target_if internal private data
2321  * @spectral_params: Pointer to Spectral parameters
2322  *
2323  * Enable use of desired Spectral parameters by configuring them into HW, and
2324  * starting Spectral scan
2325  *
2326  * Return: 0 on success, 1 on failure
2327  */
2328 int
2329 target_if_spectral_scan_enable_params(struct target_if_spectral *spectral,
2330 				      struct spectral_config *spectral_params)
2331 {
2332 	int extension_channel = 0;
2333 	int current_channel = 0;
2334 	struct target_if_spectral_ops *p_sops = NULL;
2335 	struct wlan_objmgr_vdev *vdev = NULL;
2336 
2337 	if (!spectral) {
2338 		spectral_err("SPECTRAL : Spectral is NULL");
2339 		return 1;
2340 	}
2341 
2342 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
2343 
2344 	if (!p_sops) {
2345 		spectral_err("SPECTRAL : p_sops is NULL");
2346 		return 1;
2347 	}
2348 
2349 	spectral->sc_spectral_noise_pwr_cal =
2350 	    spectral_params->ss_spectral_pri ? 1 : 0;
2351 
2352 	/* check if extension channel is present */
2353 	extension_channel = p_sops->get_extension_channel(spectral);
2354 	current_channel = p_sops->get_current_channel(spectral);
2355 
2356 	vdev = target_if_spectral_get_vdev(spectral);
2357 	if (!vdev)
2358 		return 1;
2359 
2360 	spectral->ch_width = target_if_vdev_get_ch_width(vdev);
2361 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
2362 
2363 	if (spectral->ch_width == CH_WIDTH_INVALID)
2364 		return 1;
2365 
2366 	if (spectral->capability.advncd_spectral_cap) {
2367 		spectral->lb_edge_extrabins = 0;
2368 		spectral->rb_edge_extrabins = 0;
2369 
2370 		if (spectral->is_lb_edge_extrabins_format &&
2371 		    spectral->params.ss_rpt_mode == 2) {
2372 			spectral->lb_edge_extrabins = 4;
2373 		}
2374 
2375 		if (spectral->is_rb_edge_extrabins_format &&
2376 		    spectral->params.ss_rpt_mode == 2) {
2377 			spectral->rb_edge_extrabins = 4;
2378 		}
2379 
2380 		if (spectral->ch_width == CH_WIDTH_20MHZ) {
2381 			spectral->sc_spectral_20_40_mode = 0;
2382 
2383 			spectral->spectral_numbins =
2384 			    target_if_get_fft_bin_count(
2385 				spectral->params.ss_fft_size);
2386 			spectral->spectral_fft_len =
2387 			    target_if_get_fft_bin_count(
2388 				spectral->params.ss_fft_size);
2389 			spectral->spectral_data_len =
2390 			    target_if_get_fft_bin_count(
2391 				spectral->params.ss_fft_size);
2392 			/*
2393 			 * Initialize classifier params to be sent to user
2394 			 * space classifier
2395 			 */
2396 			spectral->classifier_params.lower_chan_in_mhz =
2397 			    current_channel;
2398 			spectral->classifier_params.upper_chan_in_mhz = 0;
2399 
2400 		} else if (spectral->ch_width == CH_WIDTH_40MHZ) {
2401 			/* TODO : Remove this variable */
2402 			spectral->sc_spectral_20_40_mode = 1;
2403 			spectral->spectral_numbins =
2404 			    target_if_get_fft_bin_count(
2405 				spectral->params.ss_fft_size);
2406 			spectral->spectral_fft_len =
2407 			    target_if_get_fft_bin_count(
2408 				spectral->params.ss_fft_size);
2409 			spectral->spectral_data_len =
2410 			    target_if_get_fft_bin_count(
2411 				spectral->params.ss_fft_size);
2412 
2413 			/*
2414 			 * Initialize classifier params to be sent to user
2415 			 * space classifier
2416 			 */
2417 			if (extension_channel < current_channel) {
2418 				spectral->classifier_params.lower_chan_in_mhz =
2419 				    extension_channel;
2420 				spectral->classifier_params.upper_chan_in_mhz =
2421 				    current_channel;
2422 			} else {
2423 				spectral->classifier_params.lower_chan_in_mhz =
2424 				    current_channel;
2425 				spectral->classifier_params.upper_chan_in_mhz =
2426 				    extension_channel;
2427 			}
2428 
2429 		} else if (spectral->ch_width == CH_WIDTH_80MHZ) {
2430 			/* Set the FFT Size */
2431 			/* TODO : Remove this variable */
2432 			spectral->sc_spectral_20_40_mode = 0;
2433 			spectral->spectral_numbins =
2434 			    target_if_get_fft_bin_count(
2435 				spectral->params.ss_fft_size);
2436 			spectral->spectral_fft_len =
2437 			    target_if_get_fft_bin_count(
2438 				spectral->params.ss_fft_size);
2439 			spectral->spectral_data_len =
2440 			    target_if_get_fft_bin_count(
2441 				spectral->params.ss_fft_size);
2442 
2443 			/*
2444 			 * Initialize classifier params to be sent to user
2445 			 * space classifier
2446 			 */
2447 			spectral->classifier_params.lower_chan_in_mhz =
2448 			    current_channel;
2449 			spectral->classifier_params.upper_chan_in_mhz = 0;
2450 
2451 			/*
2452 			 * Initialize classifier params to be sent to user
2453 			 * space classifier
2454 			 */
2455 			if (extension_channel < current_channel) {
2456 				spectral->classifier_params.lower_chan_in_mhz =
2457 				    extension_channel;
2458 				spectral->classifier_params.upper_chan_in_mhz =
2459 				    current_channel;
2460 			} else {
2461 				spectral->classifier_params.lower_chan_in_mhz =
2462 				    current_channel;
2463 				spectral->classifier_params.upper_chan_in_mhz =
2464 				    extension_channel;
2465 			}
2466 
2467 		} else if (spectral->ch_width == CH_WIDTH_160MHZ) {
2468 			/* Set the FFT Size */
2469 
2470 			/* The below applies to both 160 and 80+80 cases */
2471 
2472 			/* TODO : Remove this variable */
2473 			spectral->sc_spectral_20_40_mode = 0;
2474 			spectral->spectral_numbins =
2475 			    target_if_get_fft_bin_count(
2476 				spectral->params.ss_fft_size);
2477 			spectral->spectral_fft_len =
2478 			    target_if_get_fft_bin_count(
2479 				spectral->params.ss_fft_size);
2480 			spectral->spectral_data_len =
2481 			    target_if_get_fft_bin_count(
2482 				spectral->params.ss_fft_size);
2483 
2484 			/*
2485 			 * Initialize classifier params to be sent to user
2486 			 * space classifier
2487 			 */
2488 			spectral->classifier_params.lower_chan_in_mhz =
2489 			    current_channel;
2490 			spectral->classifier_params.upper_chan_in_mhz = 0;
2491 
2492 			/*
2493 			 * Initialize classifier params to be sent to user
2494 			 * space classifier
2495 			 */
2496 			if (extension_channel < current_channel) {
2497 				spectral->classifier_params.lower_chan_in_mhz =
2498 				    extension_channel;
2499 				spectral->classifier_params.upper_chan_in_mhz =
2500 				    current_channel;
2501 			} else {
2502 				spectral->classifier_params.lower_chan_in_mhz =
2503 				    current_channel;
2504 				spectral->classifier_params.upper_chan_in_mhz =
2505 				    extension_channel;
2506 			}
2507 		}
2508 
2509 		if (spectral->spectral_numbins) {
2510 			spectral->spectral_numbins +=
2511 			    spectral->lb_edge_extrabins;
2512 			spectral->spectral_numbins +=
2513 			    spectral->rb_edge_extrabins;
2514 		}
2515 
2516 		if (spectral->spectral_fft_len) {
2517 			spectral->spectral_fft_len +=
2518 			    spectral->lb_edge_extrabins;
2519 			spectral->spectral_fft_len +=
2520 			    spectral->rb_edge_extrabins;
2521 		}
2522 
2523 		if (spectral->spectral_data_len) {
2524 			spectral->spectral_data_len +=
2525 			    spectral->lb_edge_extrabins;
2526 			spectral->spectral_data_len +=
2527 			    spectral->rb_edge_extrabins;
2528 		}
2529 	} else {
2530 		/*
2531 		 * The decision to find 20/40 mode is found based on the
2532 		 * presence of extension channel
2533 		 * instead of channel width, as the channel width can
2534 		 * dynamically change
2535 		 */
2536 
2537 		if (extension_channel == 0) {
2538 			spectral->spectral_numbins = SPECTRAL_HT20_NUM_BINS;
2539 			spectral->spectral_dc_index = SPECTRAL_HT20_DC_INDEX;
2540 			spectral->spectral_fft_len = SPECTRAL_HT20_FFT_LEN;
2541 			spectral->spectral_data_len =
2542 			    SPECTRAL_HT20_TOTAL_DATA_LEN;
2543 			/* only valid in 20-40 mode */
2544 			spectral->spectral_lower_max_index_offset = -1;
2545 			/* only valid in 20-40 mode */
2546 			spectral->spectral_upper_max_index_offset = -1;
2547 			spectral->spectral_max_index_offset =
2548 			    spectral->spectral_fft_len + 2;
2549 			spectral->sc_spectral_20_40_mode = 0;
2550 
2551 			/*
2552 			 * Initialize classifier params to be sent to user
2553 			 * space classifier
2554 			 */
2555 			spectral->classifier_params.lower_chan_in_mhz =
2556 			    current_channel;
2557 			spectral->classifier_params.upper_chan_in_mhz = 0;
2558 
2559 		} else {
2560 			spectral->spectral_numbins =
2561 			    SPECTRAL_HT40_TOTAL_NUM_BINS;
2562 			spectral->spectral_fft_len = SPECTRAL_HT40_FFT_LEN;
2563 			spectral->spectral_data_len =
2564 			    SPECTRAL_HT40_TOTAL_DATA_LEN;
2565 			spectral->spectral_dc_index = SPECTRAL_HT40_DC_INDEX;
2566 			/* only valid in 20 mode */
2567 			spectral->spectral_max_index_offset = -1;
2568 			spectral->spectral_lower_max_index_offset =
2569 			    spectral->spectral_fft_len + 2;
2570 			spectral->spectral_upper_max_index_offset =
2571 			    spectral->spectral_fft_len + 5;
2572 			spectral->sc_spectral_20_40_mode = 1;
2573 
2574 			/*
2575 			 * Initialize classifier params to be sent to user
2576 			 * space classifier
2577 			 */
2578 			if (extension_channel < current_channel) {
2579 				spectral->classifier_params.lower_chan_in_mhz =
2580 				    extension_channel;
2581 				spectral->classifier_params.upper_chan_in_mhz =
2582 				    current_channel;
2583 			} else {
2584 				spectral->classifier_params.lower_chan_in_mhz =
2585 				    current_channel;
2586 				spectral->classifier_params.upper_chan_in_mhz =
2587 				    extension_channel;
2588 			}
2589 		}
2590 	}
2591 
2592 	spectral->send_single_packet = 0;
2593 	spectral->classifier_params.spectral_20_40_mode =
2594 	    spectral->sc_spectral_20_40_mode;
2595 	spectral->classifier_params.spectral_dc_index =
2596 	    spectral->spectral_dc_index;
2597 	spectral->spectral_sent_msg = 0;
2598 	spectral->classify_scan = 0;
2599 	spectral->num_spectral_data = 0;
2600 
2601 	if (!p_sops->is_spectral_active(spectral)) {
2602 		p_sops->configure_spectral(spectral, spectral_params);
2603 		p_sops->start_spectral_scan(spectral);
2604 	} else {
2605 	}
2606 
2607 	/* get current spectral configuration */
2608 	p_sops->get_spectral_config(spectral, &spectral->params);
2609 
2610 	target_if_init_upper_lower_flags(spectral);
2611 
2612 	return 0;
2613 }
2614 
2615 /**
2616  * target_if_start_spectral_scan() - Start spectral scan
2617  * @pdev: Pointer to pdev object
2618  *
2619  * API to start spectral scan
2620  *
2621  * Return: 0 in case of success, -1 on failure
2622  */
2623 int
2624 target_if_start_spectral_scan(struct wlan_objmgr_pdev *pdev)
2625 {
2626 	struct target_if_spectral_ops *p_sops = NULL;
2627 	struct target_if_spectral *spectral = NULL;
2628 
2629 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2630 	if (!spectral) {
2631 		spectral_err("SPECTRAL : Spectral LMAC object is NUll");
2632 		return -EPERM;
2633 	}
2634 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
2635 
2636 	qdf_spin_lock(&spectral->spectral_lock);
2637 	target_if_spectral_scan_enable_params(spectral, &spectral->params);
2638 	qdf_spin_unlock(&spectral->spectral_lock);
2639 
2640 	return 0;
2641 }
2642 
2643 void
2644 target_if_stop_spectral_scan(struct wlan_objmgr_pdev *pdev)
2645 {
2646 	struct target_if_spectral_ops *p_sops = NULL;
2647 	struct target_if_spectral *spectral = NULL;
2648 
2649 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2650 	if (!spectral) {
2651 		spectral_err("SPECTRAL : Spectral LMAC object is NUll ");
2652 		return;
2653 	}
2654 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
2655 
2656 	qdf_spin_lock(&spectral->spectral_lock);
2657 	p_sops->stop_spectral_scan(spectral);
2658 	if (spectral->classify_scan) {
2659 		/* TODO : Check if this logic is necessary */
2660 		spectral->detects_control_channel = 0;
2661 		spectral->detects_extension_channel = 0;
2662 		spectral->detects_above_dc = 0;
2663 		spectral->detects_below_dc = 0;
2664 		spectral->classify_scan = 0;
2665 	}
2666 
2667 	spectral->send_single_packet = 0;
2668 	spectral->sc_spectral_scan = 0;
2669 
2670 	qdf_spin_unlock(&spectral->spectral_lock);
2671 }
2672 
2673 /**
2674  * target_if_is_spectral_active() - Get whether Spectral is active
2675  * @pdev: Pointer to pdev object
2676  *
2677  * API to get whether Spectral is active
2678  *
2679  * Return: True if Spectral is active, false if Spectral is not active
2680  */
2681 bool
2682 target_if_is_spectral_active(struct wlan_objmgr_pdev *pdev)
2683 {
2684 	struct target_if_spectral *spectral = NULL;
2685 	struct target_if_spectral_ops *p_sops = NULL;
2686 
2687 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2688 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
2689 	return p_sops->is_spectral_active(spectral);
2690 }
2691 
2692 /**
2693  * target_if_is_spectral_enabled() - Get whether Spectral is enabled
2694  * @pdev: Pointer to pdev object
2695  *
2696  * API to get whether Spectral is enabled
2697  *
2698  * Return: True if Spectral is enabled, false if Spectral is not enabled
2699  */
2700 bool
2701 target_if_is_spectral_enabled(struct wlan_objmgr_pdev *pdev)
2702 {
2703 	struct target_if_spectral *spectral = NULL;
2704 	struct target_if_spectral_ops *p_sops = NULL;
2705 
2706 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2707 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
2708 	return p_sops->is_spectral_enabled(spectral);
2709 }
2710 
2711 /**
2712  * target_if_set_debug_level() - Set debug level for Spectral
2713  * @pdev: Pointer to pdev object
2714  * @debug_level: Debug level
2715  *
2716  * API to set the debug level for Spectral
2717  *
2718  * Return: 0 in case of success
2719  */
2720 int
2721 target_if_set_debug_level(struct wlan_objmgr_pdev *pdev, uint32_t debug_level)
2722 {
2723 	spectral_debug_level = (DEBUG_SPECTRAL << debug_level);
2724 	return 0;
2725 }
2726 
2727 /**
2728  * target_if_get_debug_level() - Get debug level for Spectral
2729  * @pdev: Pointer to pdev object
2730  *
2731  * API to get the debug level for Spectral
2732  *
2733  * Return: Current debug level
2734  */
2735 uint32_t
2736 target_if_get_debug_level(struct wlan_objmgr_pdev *pdev)
2737 {
2738 	return spectral_debug_level;
2739 }
2740 
2741 /**
2742  * target_if_get_spectral_capinfo() - Get Spectral capability information
2743  * @pdev: Pointer to pdev object
2744  * @outdata: Buffer into which data should be copied
2745  *
2746  * API to get the spectral capability information
2747  *
2748  * Return: void
2749  */
2750 void
2751 target_if_get_spectral_capinfo(struct wlan_objmgr_pdev *pdev, void *outdata)
2752 {
2753 	struct target_if_spectral *spectral = NULL;
2754 
2755 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2756 	qdf_mem_copy(outdata, &spectral->capability,
2757 		     sizeof(struct spectral_caps));
2758 }
2759 
2760 /**
2761  * target_if_get_spectral_diagstats() - Get Spectral diagnostic statistics
2762  * @pdev:  Pointer to pdev object
2763  * @outdata: Buffer into which data should be copied
2764  *
2765  * API to get the spectral diagnostic statistics
2766  *
2767  * Return: void
2768  */
2769 void
2770 target_if_get_spectral_diagstats(struct wlan_objmgr_pdev *pdev, void *outdata)
2771 {
2772 	struct target_if_spectral *spectral = NULL;
2773 
2774 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2775 	qdf_mem_copy(outdata, &spectral->diag_stats,
2776 		     sizeof(struct spectral_diag_stats));
2777 }
2778 
2779 /**
2780  * target_if_register_wmi_spectral_cmd_ops() - Register wmi_spectral_cmd_ops
2781  * @cmd_ops: Pointer to the structure having wmi_spectral_cmd function pointers
2782  * @pdev: Pointer to pdev object
2783  *
2784  * API for register wmi_spectral_cmd_ops in spectral internal data structure
2785  *
2786  * Return: void
2787  */
2788 void
2789 target_if_register_wmi_spectral_cmd_ops(struct wlan_objmgr_pdev *pdev,
2790 					struct wmi_spectral_cmd_ops *cmd_ops)
2791 {
2792 	struct target_if_spectral *spectral = NULL;
2793 
2794 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2795 	spectral->param_wmi_cmd_ops.wmi_spectral_configure_cmd_send =
2796 	    cmd_ops->wmi_spectral_configure_cmd_send;
2797 	spectral->param_wmi_cmd_ops.wmi_spectral_enable_cmd_send =
2798 	    cmd_ops->wmi_spectral_enable_cmd_send;
2799 }
2800 
2801 /**
2802  * target_if_register_netlink_cb() - Register Netlink callbacks
2803  * @pdev: Pointer to pdev object
2804  * @nl_cb: Netlink callbacks to register
2805  *
2806  * Return: void
2807  */
2808 static void
2809 target_if_register_netlink_cb(
2810 	struct wlan_objmgr_pdev *pdev,
2811 	struct spectral_nl_cb *nl_cb)
2812 {
2813 	struct target_if_spectral *spectral = NULL;
2814 
2815 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2816 	qdf_mem_copy(&spectral->nl_cb, nl_cb, sizeof(struct spectral_nl_cb));
2817 
2818 	if (spectral->use_nl_bcast)
2819 		spectral->send_phy_data = spectral->nl_cb.send_nl_bcast;
2820 	else
2821 		spectral->send_phy_data = spectral->nl_cb.send_nl_unicast;
2822 }
2823 
2824 /**
2825  * target_if_use_nl_bcast() - Get whether to use broadcast/unicast while sending
2826  * Netlink messages to the application layer
2827  * @pdev: Pointer to pdev object
2828  *
2829  * Return: true for broadcast, false for unicast
2830  */
2831 static bool
2832 target_if_use_nl_bcast(struct wlan_objmgr_pdev *pdev)
2833 {
2834 	struct target_if_spectral *spectral = NULL;
2835 
2836 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2837 	return spectral->use_nl_bcast;
2838 }
2839 
2840 /**
2841  * target_if_deregister_netlink_cb() - De-register Netlink callbacks
2842  * @pdev: Pointer to pdev object
2843  *
2844  * Return: void
2845  */
2846 static void
2847 target_if_deregister_netlink_cb(struct wlan_objmgr_pdev *pdev)
2848 {
2849 	struct target_if_spectral *spectral = NULL;
2850 
2851 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2852 	if (!spectral) {
2853 		spectral_err("SPECTRAL : Module doesn't exist");
2854 		return;
2855 	}
2856 
2857 	qdf_mem_zero(&spectral->nl_cb, sizeof(struct spectral_nl_cb));
2858 }
2859 
2860 static int
2861 target_if_process_spectral_report(struct wlan_objmgr_pdev *pdev,
2862 				  void *payload)
2863 {
2864 	struct target_if_spectral *spectral = NULL;
2865 	struct target_if_spectral_ops *p_sops = NULL;
2866 
2867 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2868 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
2869 
2870 	return p_sops->process_spectral_report(pdev, payload);
2871 }
2872 
2873 void
2874 target_if_sptrl_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
2875 {
2876 	tx_ops->sptrl_tx_ops.sptrlto_pdev_spectral_init =
2877 	    target_if_pdev_spectral_init;
2878 	tx_ops->sptrl_tx_ops.sptrlto_pdev_spectral_deinit =
2879 	    target_if_pdev_spectral_deinit;
2880 	tx_ops->sptrl_tx_ops.sptrlto_set_spectral_config =
2881 	    target_if_set_spectral_config;
2882 	tx_ops->sptrl_tx_ops.sptrlto_get_spectral_config =
2883 	    target_if_get_spectral_config;
2884 	tx_ops->sptrl_tx_ops.sptrlto_start_spectral_scan =
2885 	    target_if_start_spectral_scan;
2886 	tx_ops->sptrl_tx_ops.sptrlto_stop_spectral_scan =
2887 	    target_if_stop_spectral_scan;
2888 	tx_ops->sptrl_tx_ops.sptrlto_is_spectral_active =
2889 	    target_if_is_spectral_active;
2890 	tx_ops->sptrl_tx_ops.sptrlto_is_spectral_enabled =
2891 	    target_if_is_spectral_enabled;
2892 	tx_ops->sptrl_tx_ops.sptrlto_set_debug_level =
2893 	    target_if_set_debug_level;
2894 	tx_ops->sptrl_tx_ops.sptrlto_get_debug_level =
2895 	    target_if_get_debug_level;
2896 	tx_ops->sptrl_tx_ops.sptrlto_get_spectral_capinfo =
2897 	    target_if_get_spectral_capinfo;
2898 	tx_ops->sptrl_tx_ops.sptrlto_get_spectral_diagstats =
2899 	    target_if_get_spectral_diagstats;
2900 	tx_ops->sptrl_tx_ops.sptrlto_register_wmi_spectral_cmd_ops =
2901 	    target_if_register_wmi_spectral_cmd_ops;
2902 	tx_ops->sptrl_tx_ops.sptrlto_register_netlink_cb =
2903 	    target_if_register_netlink_cb;
2904 	tx_ops->sptrl_tx_ops.sptrlto_use_nl_bcast =
2905 	    target_if_use_nl_bcast;
2906 	tx_ops->sptrl_tx_ops.sptrlto_deregister_netlink_cb =
2907 	    target_if_deregister_netlink_cb;
2908 	tx_ops->sptrl_tx_ops.sptrlto_process_spectral_report =
2909 		target_if_process_spectral_report;
2910 }
2911 qdf_export_symbol(target_if_sptrl_register_tx_ops);
2912 
2913 void
2914 target_if_spectral_send_intf_found_msg(struct wlan_objmgr_pdev *pdev,
2915 				       uint16_t cw_int, uint32_t dcs_enabled)
2916 {
2917 	struct spectral_samp_msg *msg = NULL;
2918 	struct target_if_spectral_ops *p_sops = NULL;
2919 	struct target_if_spectral *spectral = NULL;
2920 
2921 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2922 	msg  = (struct spectral_samp_msg *)spectral->nl_cb.get_nbuff(
2923 			spectral->pdev_obj);
2924 
2925 	if (msg) {
2926 		msg->int_type = cw_int ?
2927 		    SPECTRAL_DCS_INT_CW : SPECTRAL_DCS_INT_WIFI;
2928 		msg->dcs_enabled = dcs_enabled;
2929 		msg->signature = SPECTRAL_SIGNATURE;
2930 		p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
2931 		p_sops->get_mac_address(spectral, msg->macaddr);
2932 		if (spectral->send_phy_data(pdev) == 0)
2933 			spectral->spectral_sent_msg++;
2934 	}
2935 }
2936 qdf_export_symbol(target_if_spectral_send_intf_found_msg);
2937