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