xref: /wlan-dirver/qca-wifi-host-cmn/target_if/spectral/target_if_spectral_sim.c (revision 6d768494e5ce14eb1603a695c86739d12ecc6ec2)
1 /*
2  * Copyright (c) 2015,2017-2020 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 #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION
21 #include "target_if_spectral.h"
22 #include "target_if_spectral_sim.h"
23 #include "target_if_spectral_sim_int.h"
24 #include "_ieee80211.h"
25 #include "ieee80211_api.h"
26 #include "ieee80211_defines.h"
27 #include "qdf_types.h"
28 #include "ieee80211_var.h"
29 #include <wlan_mlme_dispatcher.h>
30 #include <qdf_module.h>
31 
32 /* Helper functions */
33 
34 static int target_if_populate_report_static_gen2(
35 	struct spectralsim_report *report,
36 	enum phy_ch_width width, bool is_80_80);
37 static int target_if_populate_report_static_gen3(
38 	struct spectralsim_report *report,
39 	enum phy_ch_width width, bool is_80_80);
40 static void target_if_depopulate_report(
41 	struct spectralsim_report *report);
42 
43 static int target_if_populate_reportset_static(
44 	struct spectralsim_context *simctx,
45 	struct spectralsim_reportset *reportset,
46 	enum phy_ch_width width, bool is_80_80);
47 static void target_if_depopulate_reportset(
48 	struct spectralsim_reportset *
49 	reportset);
50 
51 static int target_if_populate_simdata(struct spectralsim_context *simctx);
52 static void target_if_depopulate_simdata(struct spectralsim_context *simctx);
53 static OS_TIMER_FUNC(target_if_spectral_sim_phyerrdelivery_handler);
54 
55 /*
56  * Static configuration.
57  * For now, we will be having a single configuration per BW, and a single
58  * report per configuration (since we need the data only for ensuring correct
59  * format handling).
60  *
61  * Extend this for more functionality if required in the future.
62  */
63 
64 /**
65  * target_if_populate_report_static_gen2() - Statically populate simulation
66  * data for one report for generation 2 chipsets
67  * @report: Pointer to spectral report data instance
68  * @width : Channel bandwidth enumeration
69  *
70  * Statically populate simulation data for one report for generation 2 chipsets
71  *
72  * Return: 0 on success, negative error code on failure
73  */
74 static int
75 target_if_populate_report_static_gen2(
76 	struct spectralsim_report *report,
77 	enum phy_ch_width width)
78 {
79 	qdf_assert_always(report);
80 
81 	switch (width) {
82 	case CH_WIDTH_20MHZ:
83 		report->data = NULL;
84 		report->data = (uint8_t *)
85 		    qdf_mem_malloc(sizeof(reportdata_20_gen2));
86 
87 		if (!report->data)
88 			goto bad;
89 
90 		report->datasize = sizeof(reportdata_20_gen2);
91 		qdf_mem_copy(report->data,
92 			     reportdata_20_gen2, report->datasize);
93 
94 		qdf_mem_copy(&report->rfqual_info,
95 			     &rfqual_info_20, sizeof(report->rfqual_info));
96 
97 		qdf_mem_copy(&report->chan_info,
98 			     &chan_info_20, sizeof(report->chan_info));
99 
100 		break;
101 	case CH_WIDTH_40MHZ:
102 		report->data = NULL;
103 		report->data = (uint8_t *)
104 		    qdf_mem_malloc(sizeof(reportdata_40_gen2));
105 
106 		if (!report->data)
107 			goto bad;
108 
109 		report->datasize = sizeof(reportdata_40_gen2);
110 		qdf_mem_copy(report->data,
111 			     reportdata_40_gen2, report->datasize);
112 
113 		qdf_mem_copy(&report->rfqual_info,
114 			     &rfqual_info_40, sizeof(report->rfqual_info));
115 
116 		qdf_mem_copy(&report->chan_info,
117 			     &chan_info_40, sizeof(report->chan_info));
118 
119 		break;
120 	case CH_WIDTH_80MHZ:
121 		report->data = NULL;
122 		report->data = (uint8_t *)
123 		    qdf_mem_malloc(sizeof(reportdata_80_gen2));
124 
125 		if (!report->data)
126 			goto bad;
127 
128 		report->datasize = sizeof(reportdata_80_gen2);
129 		qdf_mem_copy(report->data,
130 			     reportdata_80_gen2, report->datasize);
131 
132 		qdf_mem_copy(&report->rfqual_info,
133 			     &rfqual_info_80, sizeof(report->rfqual_info));
134 
135 		qdf_mem_copy(&report->chan_info,
136 			     &chan_info_80, sizeof(report->chan_info));
137 
138 		break;
139 	case CH_WIDTH_80P80MHZ:
140 		report->data = NULL;
141 		report->data = (uint8_t *)
142 		    qdf_mem_malloc(sizeof(reportdata_80_80_gen2));
143 
144 		if (!report->data)
145 			goto bad;
146 
147 		report->datasize = sizeof(reportdata_80_80_gen2);
148 		qdf_mem_copy(report->data,
149 			     reportdata_80_80_gen2, report->datasize);
150 
151 		qdf_mem_copy(&report->rfqual_info,
152 			     &rfqual_info_80_80,
153 			     sizeof(report->rfqual_info));
154 
155 		qdf_mem_copy(&report->chan_info,
156 			     &chan_info_80_80,
157 			     sizeof(report->chan_info));
158 		break;
159 
160 	case CH_WIDTH_160MHZ:
161 		report->data = NULL;
162 		report->data = (uint8_t *)
163 		    qdf_mem_malloc(sizeof(reportdata_160_gen2));
164 
165 		if (!report->data)
166 			goto bad;
167 
168 		report->datasize = sizeof(reportdata_160_gen2);
169 		qdf_mem_copy(report->data,
170 			     reportdata_160_gen2, report->datasize);
171 
172 		qdf_mem_copy(&report->rfqual_info,
173 			     &rfqual_info_160,
174 			     sizeof(report->rfqual_info));
175 
176 		qdf_mem_copy(&report->chan_info,
177 			     &chan_info_160, sizeof(report->chan_info));
178 		break;
179 
180 	default:
181 		spectral_err("Unhandled width. Please correct. Asserting");
182 		qdf_assert_always(0);
183 	}
184 
185 	return 0;
186 
187  bad:
188 	return -EPERM;
189 }
190 
191 /**
192  * target_if_populate_report_static_gen3() - Statically populate simulation
193  * data for one report for generation 3 chipsets
194  * @report: Pointer to spectral report data instance
195  * @width : Channel bandwidth enumeration
196  *
197  * Statically populate simulation data for one report for generation 3 chipsets
198  *
199  * Return: 0 on success, negative error code on failure
200  */
201 static int
202 target_if_populate_report_static_gen3(
203 	struct spectralsim_report *report,
204 	enum phy_ch_width width)
205 {
206 	qdf_assert_always(report);
207 
208 	switch (width) {
209 	case CH_WIDTH_20MHZ:
210 		report->data = NULL;
211 		report->data = (uint8_t *)
212 		    qdf_mem_malloc(sizeof(reportdata_20_gen3));
213 
214 		if (!report->data)
215 			goto bad;
216 
217 		report->datasize = sizeof(reportdata_20_gen3);
218 		qdf_mem_copy(report->data,
219 			     reportdata_20_gen3, report->datasize);
220 
221 		qdf_mem_copy(&report->rfqual_info,
222 			     &rfqual_info_20, sizeof(report->rfqual_info));
223 
224 		qdf_mem_copy(&report->chan_info,
225 			     &chan_info_20, sizeof(report->chan_info));
226 
227 		break;
228 	case CH_WIDTH_40MHZ:
229 		report->data = NULL;
230 		report->data = (uint8_t *)
231 		    qdf_mem_malloc(sizeof(reportdata_40_gen3));
232 
233 		if (!report->data)
234 			goto bad;
235 
236 		report->datasize = sizeof(reportdata_40_gen3);
237 		qdf_mem_copy(report->data,
238 			     reportdata_40_gen3, report->datasize);
239 
240 		qdf_mem_copy(&report->rfqual_info,
241 			     &rfqual_info_40, sizeof(report->rfqual_info));
242 
243 		qdf_mem_copy(&report->chan_info,
244 			     &chan_info_40, sizeof(report->chan_info));
245 
246 		break;
247 	case CH_WIDTH_80MHZ:
248 		report->data = NULL;
249 		report->data = (uint8_t *)
250 		    qdf_mem_malloc(sizeof(reportdata_80_gen3));
251 
252 		if (!report->data)
253 			goto bad;
254 
255 		report->datasize = sizeof(reportdata_80_gen3);
256 		qdf_mem_copy(report->data,
257 			     reportdata_80_gen3, report->datasize);
258 
259 		qdf_mem_copy(&report->rfqual_info,
260 			     &rfqual_info_80, sizeof(report->rfqual_info));
261 
262 		qdf_mem_copy(&report->chan_info,
263 			     &chan_info_80, sizeof(report->chan_info));
264 
265 		break;
266 
267 	case CH_WIDTH_80P80MHZ:
268 		report->data = NULL;
269 		report->data = (uint8_t *)
270 		    qdf_mem_malloc(sizeof(reportdata_80_80_gen3));
271 
272 		if (!report->data)
273 			goto bad;
274 
275 		report->datasize = sizeof(reportdata_80_80_gen3);
276 		qdf_mem_copy(report->data,
277 			     reportdata_80_80_gen3, report->datasize);
278 
279 		qdf_mem_copy(&report->rfqual_info,
280 			     &rfqual_info_80_80,
281 			     sizeof(report->rfqual_info));
282 
283 		qdf_mem_copy(&report->chan_info,
284 			     &chan_info_80_80,
285 			     sizeof(report->chan_info));
286 		break;
287 
288 	case CH_WIDTH_160MHZ:
289 		report->data = NULL;
290 		report->data = (uint8_t *)
291 		    qdf_mem_malloc(sizeof(reportdata_160_gen3));
292 
293 		if (!report->data)
294 			goto bad;
295 
296 		report->datasize = sizeof(reportdata_160_gen3);
297 		qdf_mem_copy(report->data,
298 			     reportdata_160_gen3, report->datasize);
299 
300 		qdf_mem_copy(&report->rfqual_info,
301 			     &rfqual_info_160,
302 			     sizeof(report->rfqual_info));
303 
304 		qdf_mem_copy(&report->chan_info,
305 			     &chan_info_160, sizeof(report->chan_info));
306 		break;
307 
308 	default:
309 		spectral_err("Unhandled width. Please correct. Asserting");
310 		qdf_assert_always(0);
311 	}
312 
313 	return 0;
314 
315  bad:
316 	return -EPERM;
317 }
318 
319 /**
320  * target_if_depopulate_report() - Free the given instances of
321  * struct spectralsim_report
322  * @report: instance of struct spectralsim_report
323  *
324  * Free the given instances of struct spectralsim_report
325  *
326  * Return: None
327  */
328 static void
329 target_if_depopulate_report(
330 	struct spectralsim_report *report)
331 {
332 	if (!report)
333 		return;
334 
335 	if (report->data) {
336 		qdf_mem_free(report->data);
337 		report->data = NULL;
338 		report->datasize = 0;
339 	}
340 }
341 
342 /**
343  * target_if_populate_reportset_static() - Statically populate simulation data
344  * for a given configuration
345  * @simctx: Pointer to struct spectralsim_context
346  * @reportset: Set of spectral report data instances
347  * @width : Channel bandwidth enumeration
348  *
349  * Statically populate simulation data for a given configuration
350  *
351  * Return: 0 on success, negative error code on failure
352  */
353 static int
354 target_if_populate_reportset_static(
355 	struct spectralsim_context *simctx,
356 	struct spectralsim_reportset *reportset,
357 	enum phy_ch_width width)
358 {
359 	int ret = 0;
360 	struct spectralsim_report *report = NULL;
361 
362 	qdf_assert_always(reportset);
363 
364 	reportset->headreport = NULL;
365 	reportset->curr_report = NULL;
366 
367 	/* For now, we populate only one report */
368 	report = (struct spectralsim_report *)
369 	    qdf_mem_malloc(sizeof(struct spectralsim_report));
370 
371 	if (!report)
372 		goto bad;
373 
374 	qdf_mem_zero(report, sizeof(*report));
375 
376 	switch (width) {
377 	case CH_WIDTH_20MHZ:
378 		qdf_mem_copy(&reportset->config,
379 			     &config_20_1, sizeof(reportset->config));
380 
381 		ret = simctx->populate_report_static(report, CH_WIDTH_20MHZ);
382 		if (ret != 0)
383 			goto bad;
384 
385 		report->next = NULL;
386 		reportset->headreport = report;
387 		break;
388 	case CH_WIDTH_40MHZ:
389 		qdf_mem_copy(&reportset->config,
390 			     &config_40_1, sizeof(reportset->config));
391 
392 		ret = simctx->populate_report_static(report, CH_WIDTH_40MHZ);
393 		if (ret != 0)
394 			goto bad;
395 
396 		report->next = NULL;
397 		reportset->headreport = report;
398 		break;
399 	case CH_WIDTH_80MHZ:
400 		qdf_mem_copy(&reportset->config,
401 			     &config_80_1, sizeof(reportset->config));
402 
403 		ret = simctx->populate_report_static(report, CH_WIDTH_80MHZ);
404 		if (ret != 0)
405 			goto bad;
406 
407 		report->next = NULL;
408 		reportset->headreport = report;
409 		break;
410 
411 	case CH_WIDTH_80P80MHZ:
412 		qdf_mem_copy(&reportset->config,
413 			     &config_80_80_1,
414 			     sizeof(reportset->config));
415 
416 		ret = simctx->populate_report_static(report,
417 						     CH_WIDTH_80P80MHZ);
418 		if (ret != 0)
419 			goto bad;
420 
421 		report->next = NULL;
422 		reportset->headreport = report;
423 		break;
424 
425 	case CH_WIDTH_160MHZ:
426 		qdf_mem_copy(&reportset->config,
427 			     &config_160_1, sizeof(reportset->config));
428 
429 		ret = simctx->populate_report_static(report,
430 						     CH_WIDTH_160MHZ);
431 		if (ret != 0)
432 			goto bad;
433 
434 		report->next = NULL;
435 		reportset->headreport = report;
436 		break;
437 
438 	default:
439 		spectral_err("Unhandled width. Please rectify.");
440 		qdf_assert_always(0);
441 	};
442 
443 	reportset->curr_report = reportset->headreport;
444 
445 	return 0;
446 
447  bad:
448 	target_if_depopulate_reportset(reportset);
449 	return -EPERM;
450 }
451 
452 /**
453  * target_if_depopulate_reportset() - Free all the instances of
454  * struct spectralsim_reportset
455  * @report: head pointer to struct spectralsim_reportset linked list
456  *
457  * Free all the instances of struct spectralsim_reportset
458  *
459  * Return: None
460  */
461 static void
462 target_if_depopulate_reportset(
463 	struct spectralsim_reportset *reportset)
464 {
465 	struct spectralsim_report *curr_report = NULL;
466 	struct spectralsim_report *next_report = NULL;
467 
468 	if (!reportset)
469 		return;
470 
471 	curr_report = reportset->headreport;
472 
473 	while (curr_report) {
474 		next_report = curr_report->next;
475 		target_if_depopulate_report(curr_report);
476 		qdf_mem_free(curr_report);
477 		curr_report = next_report;
478 	}
479 }
480 
481 /**
482  * target_if_populate_simdata() - Populate simulation data
483  * @simctx: Pointer to struct spectralsim_context
484  *
485  * Populate simulation data
486  *
487  * Return: 0 on success, negative error code on failure
488  */
489 static int
490 target_if_populate_simdata(
491 	struct spectralsim_context *simctx)
492 {
493 	/*
494 	 * For now, we use static population. Switch to loading from a file if
495 	 * needed in the future.
496 	 */
497 
498 	simctx->bw20_headreportset = NULL;
499 	SPECTRAL_SIM_REPORTSET_ALLOCPOPL_SINGLE(simctx,
500 						simctx->bw20_headreportset,
501 						CH_WIDTH_20MHZ);
502 
503 	simctx->bw40_headreportset = NULL;
504 	SPECTRAL_SIM_REPORTSET_ALLOCPOPL_SINGLE(simctx,
505 						simctx->bw40_headreportset,
506 						CH_WIDTH_40MHZ);
507 
508 	simctx->bw80_headreportset = NULL;
509 	SPECTRAL_SIM_REPORTSET_ALLOCPOPL_SINGLE(simctx,
510 						simctx->bw80_headreportset,
511 						CH_WIDTH_80MHZ);
512 
513 	simctx->bw160_headreportset = NULL;
514 	SPECTRAL_SIM_REPORTSET_ALLOCPOPL_SINGLE(simctx,
515 						simctx->bw160_headreportset,
516 						CH_WIDTH_160MHZ);
517 
518 	simctx->bw80_80_headreportset = NULL;
519 	SPECTRAL_SIM_REPORTSET_ALLOCPOPL_SINGLE(simctx,
520 						simctx->bw80_80_headreportset,
521 						CH_WIDTH_80P80MHZ);
522 
523 	simctx->curr_reportset = NULL;
524 
525 	simctx->is_enabled = false;
526 	simctx->is_active = false;
527 
528 	simctx->ssim_starting_tsf64 = 0;
529 	simctx->ssim_count = 0;
530 	simctx->ssim_period_ms = 0;
531 
532 	return 0;
533 }
534 
535 /**
536  * target_if_depopulate_simdata() - De-populate simulation data
537  * @simctx: Pointer to struct spectralsim_context
538  *
539  * De-populate simulation data
540  *
541  * Return: none
542  */
543 static void
544 target_if_depopulate_simdata(
545 	struct spectralsim_context *simctx)
546 {
547 	if (!simctx)
548 		return;
549 
550 	SPECTRAL_SIM_REPORTSET_DEPOPLFREE_LIST(simctx->bw20_headreportset);
551 	SPECTRAL_SIM_REPORTSET_DEPOPLFREE_LIST(simctx->bw40_headreportset);
552 	SPECTRAL_SIM_REPORTSET_DEPOPLFREE_LIST(simctx->bw80_headreportset);
553 	SPECTRAL_SIM_REPORTSET_DEPOPLFREE_LIST(simctx->bw160_headreportset);
554 	SPECTRAL_SIM_REPORTSET_DEPOPLFREE_LIST(simctx->bw80_80_headreportset);
555 }
556 
557 /**
558  * target_if_spectral_sim_phyerrdelivery_handler() - Phyerr delivery handler
559  *
560  * Return: none
561  */
562 static
563 OS_TIMER_FUNC(target_if_spectral_sim_phyerrdelivery_handler)
564 {
565 	struct target_if_spectral *spectral = NULL;
566 	struct spectralsim_context *simctx = NULL;
567 	struct spectralsim_reportset *curr_reportset = NULL;
568 	struct spectralsim_report *curr_report = NULL;
569 	struct target_if_spectral_acs_stats acs_stats;
570 	uint64_t curr_tsf64 = 0;
571 	struct target_if_spectral_ops *p_sops;
572 
573 	OS_GET_TIMER_ARG(spectral, struct target_if_spectral *);
574 	qdf_assert_always(spectral);
575 
576 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
577 	qdf_assert_always(spectral);
578 
579 	simctx = (struct spectralsim_context *)spectral->simctx;
580 	qdf_assert_always(simctx);
581 
582 	if (!simctx->is_active)
583 		return;
584 
585 	curr_reportset = simctx->curr_reportset;
586 	qdf_assert_always(curr_reportset);
587 
588 	curr_report = curr_reportset->curr_report;
589 	qdf_assert_always(curr_report);
590 
591 	qdf_assert_always(curr_reportset->headreport);
592 
593 	/*
594 	 * We use a simulation TSF since in offload architectures we can't
595 	 * expect to
596 	 * get an accurate current TSF from HW.
597 	 * In case of TSF wrap over, we'll use it as-is for now since the
598 	 * simulation
599 	 * is intended only for format verification.
600 	 */
601 	curr_tsf64 = simctx->ssim_starting_tsf64 +
602 	    ((simctx->ssim_period_ms * simctx->ssim_count) * 1000);
603 
604 	p_sops->spectral_process_phyerr(spectral,
605 					curr_report->data,
606 					curr_report->datasize,
607 					&curr_report->rfqual_info,
608 					&curr_report->chan_info,
609 					curr_tsf64, &acs_stats);
610 
611 	simctx->ssim_count++;
612 
613 	if (curr_report->next)
614 		curr_reportset->curr_report = curr_report->next;
615 	else
616 		curr_reportset->curr_report = curr_reportset->headreport;
617 
618 	if (curr_reportset->config.ss_count != 0 &&
619 	    simctx->ssim_count == curr_reportset->config.ss_count) {
620 		target_if_spectral_sops_sim_stop_scan(spectral);
621 	} else {
622 		qdf_timer_start(&simctx->ssim_pherrdelivery_timer,
623 				simctx->ssim_period_ms);
624 	}
625 }
626 
627 /* Module services */
628 
629 int
630 target_if_spectral_sim_attach(struct target_if_spectral *spectral)
631 {
632 	struct spectralsim_context *simctx = NULL;
633 
634 	qdf_assert_always(spectral);
635 
636 	simctx = (struct spectralsim_context *)
637 	    qdf_mem_malloc(sizeof(struct spectralsim_context));
638 
639 	if (!simctx)
640 		return -EPERM;
641 
642 	qdf_mem_zero(simctx, sizeof(*simctx));
643 
644 	spectral->simctx = simctx;
645 
646 	if (spectral->spectral_gen == SPECTRAL_GEN2)
647 		simctx->populate_report_static =
648 			target_if_populate_report_static_gen2;
649 	else if (spectral->spectral_gen == SPECTRAL_GEN3)
650 		simctx->populate_report_static =
651 			target_if_populate_report_static_gen3;
652 
653 	if (target_if_populate_simdata(simctx) != 0) {
654 		qdf_mem_free(simctx);
655 		spectral->simctx = NULL;
656 		spectral_err("Spectral simulation attach failed");
657 		return -EPERM;
658 	}
659 
660 	qdf_timer_init(NULL,
661 		       &simctx->ssim_pherrdelivery_timer,
662 		       target_if_spectral_sim_phyerrdelivery_handler,
663 		       (void *)(spectral), QDF_TIMER_TYPE_WAKE_APPS);
664 
665 	spectral_info("Spectral simulation attached");
666 
667 	return 0;
668 }
669 
670 void
671 target_if_spectral_sim_detach(struct target_if_spectral *spectral)
672 {
673 	struct spectralsim_context *simctx = NULL;
674 
675 	qdf_assert_always(spectral);
676 
677 	simctx = (struct spectralsim_context *)spectral->simctx;
678 	qdf_assert_always(simctx);
679 
680 	qdf_timer_free(&simctx->ssim_pherrdelivery_timer);
681 
682 	target_if_depopulate_simdata(simctx);
683 	qdf_mem_free(simctx);
684 	spectral->simctx = NULL;
685 
686 	spectral_info("Spectral simulation detached");
687 }
688 
689 uint32_t
690 target_if_spectral_sops_sim_is_active(void *arg)
691 {
692 	struct target_if_spectral *spectral = NULL;
693 	struct spectralsim_context *simctx = NULL;
694 
695 	spectral = (struct target_if_spectral *)arg;
696 	qdf_assert_always(spectral);
697 
698 	simctx = (struct spectralsim_context *)spectral->simctx;
699 	qdf_assert_always(simctx);
700 
701 	return simctx->is_active;
702 }
703 qdf_export_symbol(target_if_spectral_sops_sim_is_active);
704 
705 uint32_t
706 target_if_spectral_sops_sim_is_enabled(void *arg)
707 {
708 	struct target_if_spectral *spectral = NULL;
709 	struct spectralsim_context *simctx = NULL;
710 
711 	spectral = (struct target_if_spectral *)arg;
712 	qdf_assert_always(spectral);
713 
714 	simctx = (struct spectralsim_context *)spectral->simctx;
715 	qdf_assert_always(simctx);
716 
717 	return simctx->is_enabled;
718 }
719 qdf_export_symbol(target_if_spectral_sops_sim_is_enabled);
720 
721 uint32_t
722 target_if_spectral_sops_sim_start_scan(void *arg)
723 {
724 	struct target_if_spectral *spectral = NULL;
725 	struct spectralsim_context *simctx = NULL;
726 
727 	spectral = (struct target_if_spectral *)arg;
728 	qdf_assert_always(spectral);
729 
730 	simctx = (struct spectralsim_context *)spectral->simctx;
731 	qdf_assert_always(simctx);
732 
733 	if (!simctx->curr_reportset) {
734 		spectral_err("Spectral simulation: No current report set configured  - unable to start simulated Spectral scan");
735 		return 0;
736 	}
737 
738 	if (!simctx->curr_reportset->curr_report) {
739 		spectral_err("Spectral simulation: No report data instances populated - unable to start simulated Spectral scan");
740 		return 0;
741 	}
742 
743 	if (!simctx->is_enabled)
744 		simctx->is_enabled = true;
745 
746 	simctx->is_active = true;
747 
748 	/* Hardcoding current time as zero since it is simulation */
749 	simctx->ssim_starting_tsf64 = 0;
750 	simctx->ssim_count = 0;
751 
752 	/*
753 	 * TODO: Support high resolution timer in microseconds if required, so
754 	 * that
755 	 * we can support default periods such as ~200 us.  For now, we use 1
756 	 * millisecond since the current use case for the simulation is to
757 	 * validate
758 	 * formats rather than have a time dependent classification.
759 	 */
760 	simctx->ssim_period_ms = 1;
761 
762 	qdf_timer_start(&simctx->ssim_pherrdelivery_timer,
763 			simctx->ssim_period_ms);
764 
765 	return 1;
766 }
767 qdf_export_symbol(target_if_spectral_sops_sim_start_scan);
768 
769 uint32_t
770 target_if_spectral_sops_sim_stop_scan(void *arg)
771 {
772 	struct target_if_spectral *spectral = NULL;
773 	struct spectralsim_context *simctx = NULL;
774 
775 	spectral = (struct target_if_spectral *)arg;
776 	qdf_assert_always(spectral);
777 
778 	simctx = (struct spectralsim_context *)spectral->simctx;
779 	qdf_assert_always(simctx);
780 
781 	qdf_timer_stop(&simctx->ssim_pherrdelivery_timer);
782 
783 	simctx->is_active = false;
784 	simctx->is_enabled = false;
785 
786 	simctx->ssim_starting_tsf64 = 0;
787 	simctx->ssim_count = 0;
788 	simctx->ssim_period_ms = 0;
789 
790 	return 1;
791 }
792 qdf_export_symbol(target_if_spectral_sops_sim_stop_scan);
793 
794 #ifdef SPECTRAL_SIM_DUMP_PARAM_DATA
795 static void
796 target_if_log_sim_spectral_params(struct spectral_config *params)
797 {
798 	int i = 0;
799 
800 	spectral_debug("\n");
801 
802 	spectral_debug("Spectral simulation: Param data dump:\nss_fft_period=%hu\nss_period=%hu\nss_count=%hu\nss_short_report=%hu\nradar_bin_thresh_sel=%hhu\nss_spectral_pri=%hu\nss_fft_size=%hu\nss_gc_ena=%hu\nss_restart_ena=%hu\nss_noise_floor_ref=%hu\nss_init_delay=%hu\nss_nb_tone_thr=%hu\nss_str_bin_thr=%hu\nss_wb_rpt_mode=%hu\nss_rssi_rpt_mode=%hu\nss_rssi_thr=%hu\nss_pwr_format=%hu\nss_rpt_mode=%hu\nss_bin_scale=%hu\nss_dbm_adj=%hu\nss_chn_mask=%hu\nss_nf_temp_data=%d",
803 		       params->ss_fft_period,
804 		       params->ss_period,
805 		       params->ss_count,
806 		       params->ss_short_report,
807 		       params->radar_bin_thresh_sel,
808 		       params->ss_spectral_pri,
809 		       params->ss_fft_size,
810 		       params->ss_gc_ena,
811 		       params->ss_restart_ena,
812 		       params->ss_noise_floor_ref,
813 		       params->ss_init_delay,
814 		       params->ss_nb_tone_thr,
815 		       params->ss_str_bin_thr,
816 		       params->ss_wb_rpt_mode,
817 		       params->ss_rssi_rpt_mode,
818 		       params->ss_rssi_thr,
819 		       params->ss_pwr_format,
820 		       params->ss_rpt_mode,
821 		       params->ss_bin_scale,
822 		       params->ss_dbm_adj,
823 		       params->ss_chn_mask, params->ss_nf_temp_data);
824 
825 	for (i = 0; i < AH_MAX_CHAINS * 2; i++)
826 		spectral_debug("ss_nf_cal[%d]=%hhd", i, params->ss_nf_cal[i]);
827 
828 	for (i = 0; i < AH_MAX_CHAINS * 2; i++)
829 		spectral_debug("ss_nf_pwr[%d]=%hhd", i, params->ss_nf_pwr[i]);
830 
831 	spectral_info("\n");
832 }
833 #else
834 
835 static void
836 target_if_log_sim_spectral_params(struct spectral_config *params)
837 {
838 }
839 #endif				/* SPECTRAL_SIM_DUMP_PARAM_DATA */
840 
841 uint32_t
842 target_if_spectral_sops_sim_configure_params(
843 	void *arg,
844 	struct spectral_config *params)
845 {
846 	struct target_if_spectral *spectral = NULL;
847 	struct spectralsim_context *simctx = NULL;
848 	enum wlan_phymode phymode;
849 	uint8_t bw;
850 	struct spectralsim_reportset *des_headreportset = NULL;
851 	struct spectralsim_reportset *temp_reportset = NULL;
852 	bool is_invalid_width = false;
853 	struct wlan_objmgr_vdev *vdev = NULL;
854 
855 	qdf_assert_always(params);
856 	target_if_log_sim_spectral_params(params);
857 	spectral = (struct target_if_spectral *)arg;
858 	qdf_assert_always(spectral);
859 
860 	simctx = (struct spectralsim_context *)spectral->simctx;
861 	qdf_assert_always(simctx);
862 
863 	vdev = target_if_spectral_get_vdev(spectral);
864 	if (!vdev) {
865 		spectral_warn("Spectral simulation: No VAPs found - not proceeding with param config.");
866 		return 0;
867 	}
868 
869 	bw = target_if_vdev_get_ch_width(vdev);
870 
871 	switch (bw) {
872 	case CH_WIDTH_20MHZ:
873 		des_headreportset = simctx->bw20_headreportset;
874 		break;
875 	case CH_WIDTH_40MHZ:
876 		des_headreportset = simctx->bw40_headreportset;
877 		break;
878 	case CH_WIDTH_80MHZ:
879 		des_headreportset = simctx->bw80_headreportset;
880 		break;
881 	case CH_WIDTH_160MHZ:
882 		des_headreportset = simctx->bw160_headreportset;
883 		break;
884 	case CH_WIDTH_80P80MHZ:
885 		des_headreportset = simctx->bw80_80_headreportset;
886 		break;
887 	case CH_WIDTH_INVALID:
888 		spectral_err("Spectral simulation: Invalid width configured - not proceeding with param config.");
889 		is_invalid_width = true;
890 	default:
891 		spectral_err("Spectral simulation: Unknown width %u...asserting",
892 			     bw);
893 		qdf_assert_always(0);
894 		break;
895 	}
896 
897 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
898 
899 	if (is_invalid_width)
900 		return 0;
901 
902 	if (!des_headreportset) {
903 		spectral_warn("Spectral simulation: No simulation data present for configured bandwidth/PHY mode - unable to proceed  with param config.");
904 		return 0;
905 	}
906 
907 	simctx->curr_reportset = NULL;
908 	temp_reportset = des_headreportset;
909 
910 	while (temp_reportset) {
911 		if (qdf_mem_cmp(&temp_reportset->config,
912 				params, sizeof(struct spectral_config)) == 0) {
913 			/* Found a matching config. We are done. */
914 			simctx->curr_reportset = temp_reportset;
915 			break;
916 		}
917 
918 		temp_reportset = temp_reportset->next;
919 	}
920 
921 	if (!simctx->curr_reportset) {
922 		spectral_warn("Spectral simulation: No simulation data present for desired Spectral configuration - unable to proceed with param config.");
923 		return 0;
924 	}
925 
926 	if (!simctx->curr_reportset->curr_report) {
927 		spectral_warn("Spectral simulation: No report data instances populated for desired Spectral configuration - unable to proceed with param config");
928 		return 0;
929 	}
930 
931 	return 1;
932 }
933 qdf_export_symbol(target_if_spectral_sops_sim_configure_params);
934 
935 uint32_t
936 target_if_spectral_sops_sim_get_params(
937 	void *arg, struct spectral_config *params)
938 {
939 	struct target_if_spectral *spectral = NULL;
940 	struct spectralsim_context *simctx = NULL;
941 
942 	qdf_assert_always(params);
943 
944 	spectral = (struct target_if_spectral *)arg;
945 	qdf_assert_always(spectral);
946 
947 	simctx = (struct spectralsim_context *)spectral->simctx;
948 	qdf_assert_always(simctx);
949 
950 	if (!simctx->curr_reportset) {
951 		spectral_warn("Spectral simulation: No configured reportset found.");
952 		return 0;
953 	}
954 
955 	qdf_mem_copy(params, &simctx->curr_reportset->config, sizeof(*params));
956 
957 	return 1;
958 }
959 qdf_export_symbol(target_if_spectral_sops_sim_get_params);
960 
961 #endif				/* QCA_SUPPORT_SPECTRAL_SIMULATION */
962