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