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