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