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