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