xref: /wlan-driver/qca-wifi-host-cmn/target_if/spectral/target_if_spectral_phyerr.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2011,2017-2021 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2022-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 #include <osdep.h>
21*5113495bSYour Name #include <qdf_types.h>
22*5113495bSYour Name #include <qdf_module.h>
23*5113495bSYour Name #include <wlan_tgt_def_config.h>
24*5113495bSYour Name #include <hif.h>
25*5113495bSYour Name #include <hif_hw_version.h>
26*5113495bSYour Name #include <wmi_unified_api.h>
27*5113495bSYour Name #include <target_if_spectral.h>
28*5113495bSYour Name #include <wlan_lmac_if_def.h>
29*5113495bSYour Name #include <wlan_osif_priv.h>
30*5113495bSYour Name #include <reg_services_public_struct.h>
31*5113495bSYour Name #include <target_if.h>
32*5113495bSYour Name #ifdef DIRECT_BUF_RX_ENABLE
33*5113495bSYour Name #include <target_if_direct_buf_rx_api.h>
34*5113495bSYour Name #endif
35*5113495bSYour Name extern int spectral_debug_level;
36*5113495bSYour Name 
37*5113495bSYour Name #ifdef WLAN_CONV_SPECTRAL_ENABLE
38*5113495bSYour Name 
39*5113495bSYour Name #define SPECTRAL_HEXDUMP_OCTET_PRINT_SIZE           (3)
40*5113495bSYour Name #define SPECTRAL_HEXDUMP_NUM_OCTETS_PER_LINE        (16)
41*5113495bSYour Name #define SPECTRAL_HEXDUMP_EXTRA_BUFFER_PER_LINE      (16)
42*5113495bSYour Name 
43*5113495bSYour Name /*
44*5113495bSYour Name  * Provision for the expected hexdump line size as follows:
45*5113495bSYour Name  *
46*5113495bSYour Name  * Size per octet multiplied by number of octets per line
47*5113495bSYour Name  * +
48*5113495bSYour Name  * ASCII representation which is equivalent in print size to number of octets
49*5113495bSYour Name  * per line
50*5113495bSYour Name  * +
51*5113495bSYour Name  * Some extra buffer
52*5113495bSYour Name  */
53*5113495bSYour Name #define SPECTRAL_HEXDUMP_LINESIZE                           \
54*5113495bSYour Name 		((SPECTRAL_HEXDUMP_OCTET_PRINT_SIZE *       \
55*5113495bSYour Name 		  SPECTRAL_HEXDUMP_NUM_OCTETS_PER_LINE) +   \
56*5113495bSYour Name 		 SPECTRAL_HEXDUMP_NUM_OCTETS_PER_LINE +     \
57*5113495bSYour Name 		 SPECTRAL_HEXDUMP_EXTRA_BUFFER_PER_LINE)
58*5113495bSYour Name 
59*5113495bSYour Name /**
60*5113495bSYour Name  * target_if_spectral_hexdump() - Print hexdump of the given buffer
61*5113495bSYour Name  * @_buf: Pointer to buffer
62*5113495bSYour Name  * @_len: Length of the buffer
63*5113495bSYour Name  *
64*5113495bSYour Name  * Print the hexdump of buffer upto given length. Print upto
65*5113495bSYour Name  * SPECTRAL_HEXDUMP_NUM_OCTETS_PER_LINE per line, followed by the ASCII
66*5113495bSYour Name  * representation of these octets.
67*5113495bSYour Name  */
target_if_spectral_hexdump(unsigned char * _buf,int _len)68*5113495bSYour Name static inline void target_if_spectral_hexdump(unsigned char *_buf, int _len)
69*5113495bSYour Name {
70*5113495bSYour Name 	int i, mod;
71*5113495bSYour Name 	unsigned char ascii[SPECTRAL_HEXDUMP_NUM_OCTETS_PER_LINE + 1];
72*5113495bSYour Name 	unsigned char *pc = (_buf);
73*5113495bSYour Name 	char hexdump_line[SPECTRAL_HEXDUMP_LINESIZE + 1];
74*5113495bSYour Name 	int loc = 0;
75*5113495bSYour Name 
76*5113495bSYour Name 	qdf_mem_zero(hexdump_line, sizeof(hexdump_line));
77*5113495bSYour Name 
78*5113495bSYour Name 	if (_len <= 0) {
79*5113495bSYour Name 		spectral_err("buffer len is %d, too short", _len);
80*5113495bSYour Name 		return;
81*5113495bSYour Name 	}
82*5113495bSYour Name 
83*5113495bSYour Name 	for (i = 0; i < _len; i++) {
84*5113495bSYour Name 		mod = i % SPECTRAL_HEXDUMP_NUM_OCTETS_PER_LINE;
85*5113495bSYour Name 
86*5113495bSYour Name 		if (!mod) {
87*5113495bSYour Name 			if (i) {
88*5113495bSYour Name 				if (loc >= sizeof(hexdump_line)) {
89*5113495bSYour Name 					spectral_err("loc index is %u, greater than hexdump_line array size",
90*5113495bSYour Name 						     loc);
91*5113495bSYour Name 					return;
92*5113495bSYour Name 				}
93*5113495bSYour Name 				loc += snprintf(&hexdump_line[loc],
94*5113495bSYour Name 						sizeof(hexdump_line) - loc,
95*5113495bSYour Name 						"  %s", ascii);
96*5113495bSYour Name 				spectral_debug("%s", hexdump_line);
97*5113495bSYour Name 				qdf_mem_zero(hexdump_line,
98*5113495bSYour Name 					     sizeof(hexdump_line));
99*5113495bSYour Name 				loc = 0;
100*5113495bSYour Name 			}
101*5113495bSYour Name 		}
102*5113495bSYour Name 
103*5113495bSYour Name 		if (loc >= sizeof(hexdump_line)) {
104*5113495bSYour Name 			spectral_err("loc index is %u, greater than hexdump_line array size",
105*5113495bSYour Name 				     loc);
106*5113495bSYour Name 			return;
107*5113495bSYour Name 		}
108*5113495bSYour Name 		loc += snprintf(&hexdump_line[loc], sizeof(hexdump_line) - loc,
109*5113495bSYour Name 				" %02x", pc[i]);
110*5113495bSYour Name 
111*5113495bSYour Name 		if ((pc[i] < 0x20) || (pc[i] > 0x7e))
112*5113495bSYour Name 			ascii[mod] = '.';
113*5113495bSYour Name 		else
114*5113495bSYour Name 			ascii[mod] = pc[i];
115*5113495bSYour Name 		ascii[(mod) + 1] = '\0';
116*5113495bSYour Name 	}
117*5113495bSYour Name 
118*5113495bSYour Name 	while ((i % SPECTRAL_HEXDUMP_NUM_OCTETS_PER_LINE) != 0) {
119*5113495bSYour Name 		if (loc >= sizeof(hexdump_line)) {
120*5113495bSYour Name 			spectral_err("loc index is %u, greater than hexdump_line array size",
121*5113495bSYour Name 				     loc);
122*5113495bSYour Name 			return;
123*5113495bSYour Name 		}
124*5113495bSYour Name 		loc += snprintf(&hexdump_line[loc], sizeof(hexdump_line) - loc,
125*5113495bSYour Name 				"   ");
126*5113495bSYour Name 		i++;
127*5113495bSYour Name 	}
128*5113495bSYour Name 
129*5113495bSYour Name 	if (loc >= sizeof(hexdump_line)) {
130*5113495bSYour Name 		spectral_err("loc index is %u, greater than hexdump_line array size",
131*5113495bSYour Name 			     loc);
132*5113495bSYour Name 		return;
133*5113495bSYour Name 	}
134*5113495bSYour Name 	snprintf(&hexdump_line[loc], sizeof(hexdump_line) - loc, "  %s", ascii);
135*5113495bSYour Name 	spectral_debug("%s", hexdump_line);
136*5113495bSYour Name }
137*5113495bSYour Name 
138*5113495bSYour Name /**
139*5113495bSYour Name  * target_if_print_buf() - Prints given buffer for given length
140*5113495bSYour Name  * @pbuf: Pointer to buffer
141*5113495bSYour Name  * @len: length
142*5113495bSYour Name  *
143*5113495bSYour Name  * Prints given buffer for given length
144*5113495bSYour Name  *
145*5113495bSYour Name  * Return: void
146*5113495bSYour Name  */
147*5113495bSYour Name static void
target_if_print_buf(uint8_t * pbuf,int len)148*5113495bSYour Name target_if_print_buf(uint8_t *pbuf, int len)
149*5113495bSYour Name {
150*5113495bSYour Name 	int i = 0;
151*5113495bSYour Name 
152*5113495bSYour Name 	for (i = 0; i < len; i++) {
153*5113495bSYour Name 		spectral_debug("%02X ", pbuf[i]);
154*5113495bSYour Name 		if (i % 32 == 31)
155*5113495bSYour Name 			spectral_debug("\n");
156*5113495bSYour Name 	}
157*5113495bSYour Name }
158*5113495bSYour Name 
159*5113495bSYour Name int
target_if_spectral_dump_fft(uint8_t * pfft,int fftlen)160*5113495bSYour Name target_if_spectral_dump_fft(uint8_t *pfft, int fftlen)
161*5113495bSYour Name {
162*5113495bSYour Name 	int i = 0;
163*5113495bSYour Name 
164*5113495bSYour Name 	/*
165*5113495bSYour Name 	 * TODO : Do not delete the following print
166*5113495bSYour Name 	 *        The scripts used to validate Spectral depend on this Print
167*5113495bSYour Name 	 */
168*5113495bSYour Name 	spectral_debug("SPECTRAL : FFT Length is 0x%x (%d)", fftlen, fftlen);
169*5113495bSYour Name 
170*5113495bSYour Name 	spectral_debug("fft_data # ");
171*5113495bSYour Name 	for (i = 0; i < fftlen; i++)
172*5113495bSYour Name 		spectral_debug("%d ", pfft[i]);
173*5113495bSYour Name 	spectral_debug("\n");
174*5113495bSYour Name 	return 0;
175*5113495bSYour Name }
176*5113495bSYour Name 
target_if_spectral_fw_hang(struct target_if_spectral * spectral)177*5113495bSYour Name QDF_STATUS target_if_spectral_fw_hang(struct target_if_spectral *spectral)
178*5113495bSYour Name {
179*5113495bSYour Name 	struct crash_inject param;
180*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev;
181*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
182*5113495bSYour Name 	struct target_if_psoc_spectral *psoc_spectral;
183*5113495bSYour Name 
184*5113495bSYour Name 	if (!spectral) {
185*5113495bSYour Name 		spectral_err("Spectral LMAC object is null");
186*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
187*5113495bSYour Name 	}
188*5113495bSYour Name 
189*5113495bSYour Name 	pdev = spectral->pdev_obj;
190*5113495bSYour Name 	if (!pdev) {
191*5113495bSYour Name 		spectral_err("pdev is null");
192*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
193*5113495bSYour Name 	}
194*5113495bSYour Name 
195*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
196*5113495bSYour Name 	if (!psoc) {
197*5113495bSYour Name 		spectral_err("psoc is null");
198*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
199*5113495bSYour Name 	}
200*5113495bSYour Name 
201*5113495bSYour Name 	psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
202*5113495bSYour Name 	if (!psoc_spectral) {
203*5113495bSYour Name 		spectral_err("spectral psoc object is null");
204*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
205*5113495bSYour Name 	}
206*5113495bSYour Name 
207*5113495bSYour Name 	qdf_mem_set(&param, sizeof(param), 0);
208*5113495bSYour Name 	param.type = 1; //RECOVERY_SIM_ASSERT
209*5113495bSYour Name 
210*5113495bSYour Name 	return psoc_spectral->wmi_ops.wmi_spectral_crash_inject(
211*5113495bSYour Name 		GET_WMI_HDL_FROM_PDEV(spectral->pdev_obj), &param);
212*5113495bSYour Name }
213*5113495bSYour Name 
214*5113495bSYour Name #ifdef OPTIMIZED_SAMP_MESSAGE
215*5113495bSYour Name void
target_if_dbg_print_samp_msg(struct spectral_samp_msg * ss_msg)216*5113495bSYour Name target_if_dbg_print_samp_msg(struct spectral_samp_msg *ss_msg)
217*5113495bSYour Name {
218*5113495bSYour Name 	int span, det;
219*5113495bSYour Name 	struct samp_detector_info *det_info;
220*5113495bSYour Name 	struct samp_freq_span_info *span_info;
221*5113495bSYour Name 
222*5113495bSYour Name 	spectral_dbg_line();
223*5113495bSYour Name 	spectral_debug("Spectral Message");
224*5113495bSYour Name 	spectral_dbg_line();
225*5113495bSYour Name 	spectral_debug("Signature        :   0x%x", ss_msg->signature);
226*5113495bSYour Name 	spectral_debug("Freq             :   %u", ss_msg->pri20_freq);
227*5113495bSYour Name 	spectral_debug("sscan width      :   %d", ss_msg->sscan_bw);
228*5113495bSYour Name 	spectral_debug("sscan cfreq1     :   %u", ss_msg->sscan_cfreq1);
229*5113495bSYour Name 	spectral_debug("sscan cfreq2     :   %u", ss_msg->sscan_cfreq2);
230*5113495bSYour Name 	spectral_debug("bin power count  :   %d", ss_msg->bin_pwr_count);
231*5113495bSYour Name 	spectral_debug("Number of spans  :   %d", ss_msg->num_freq_spans);
232*5113495bSYour Name 	spectral_dbg_line();
233*5113495bSYour Name 	for (span = 0; span < ss_msg->num_freq_spans; span++) {
234*5113495bSYour Name 		span_info = &ss_msg->freq_span_info[span];
235*5113495bSYour Name 		spectral_debug("-------- Span ID : %d --------", span);
236*5113495bSYour Name 		spectral_debug("Number of detectors  :  %d",
237*5113495bSYour Name 			       span_info->num_detectors);
238*5113495bSYour Name 		spectral_dbg_line();
239*5113495bSYour Name 		for (det = 0; det < span_info->num_detectors; det++) {
240*5113495bSYour Name 			det_info = &span_info->detector_info[det];
241*5113495bSYour Name 			spectral_debug("------ Detector ID : %d ------", det);
242*5113495bSYour Name 			spectral_dbg_line();
243*5113495bSYour Name 			spectral_debug("RSSI            : %d", det_info->rssi);
244*5113495bSYour Name 			spectral_debug("Timestamp       : %u",
245*5113495bSYour Name 				       det_info->timestamp);
246*5113495bSYour Name 			spectral_debug("Start bin index : %d",
247*5113495bSYour Name 				       det_info->start_bin_idx);
248*5113495bSYour Name 			spectral_debug("End bin index   : %d",
249*5113495bSYour Name 				       det_info->end_bin_idx);
250*5113495bSYour Name 			spectral_debug("Start frequency : %d",
251*5113495bSYour Name 				       det_info->start_frequency);
252*5113495bSYour Name 			spectral_debug("End frequency   : %d",
253*5113495bSYour Name 				       det_info->end_frequency);
254*5113495bSYour Name 			spectral_dbg_line();
255*5113495bSYour Name 		}
256*5113495bSYour Name 	}
257*5113495bSYour Name }
258*5113495bSYour Name #else
259*5113495bSYour Name void
target_if_dbg_print_samp_param(struct target_if_samp_msg_params * p)260*5113495bSYour Name target_if_dbg_print_samp_param(struct target_if_samp_msg_params *p)
261*5113495bSYour Name {
262*5113495bSYour Name 	spectral_debug("\nSAMP Packet : -------------------- START --------------------");
263*5113495bSYour Name 	spectral_debug("Freq        = %d", p->freq);
264*5113495bSYour Name 	spectral_debug("RSSI        = %d", p->rssi);
265*5113495bSYour Name 	spectral_debug("Bin Count   = %d", p->pwr_count);
266*5113495bSYour Name 	spectral_debug("Timestamp   = %d", p->tstamp);
267*5113495bSYour Name 	spectral_debug("SAMP Packet : -------------------- END -----------------------");
268*5113495bSYour Name }
269*5113495bSYour Name 
270*5113495bSYour Name void
target_if_dbg_print_samp_msg(struct spectral_samp_msg * ss_msg)271*5113495bSYour Name target_if_dbg_print_samp_msg(struct spectral_samp_msg *ss_msg)
272*5113495bSYour Name {
273*5113495bSYour Name 	int i = 0;
274*5113495bSYour Name 
275*5113495bSYour Name 	struct spectral_samp_data *p = &ss_msg->samp_data;
276*5113495bSYour Name 	struct spectral_classifier_params *pc = &p->classifier_params;
277*5113495bSYour Name 	struct interf_src_rsp *pi = &p->interf_list;
278*5113495bSYour Name 
279*5113495bSYour Name 	spectral_dbg_line();
280*5113495bSYour Name 	spectral_debug("Spectral Message");
281*5113495bSYour Name 	spectral_dbg_line();
282*5113495bSYour Name 	spectral_debug("Signature   :   0x%x", ss_msg->signature);
283*5113495bSYour Name 	spectral_debug("Freq        :   %d", ss_msg->freq);
284*5113495bSYour Name 	spectral_debug("Freq load   :   %d", ss_msg->freq_loading);
285*5113495bSYour Name 	spectral_debug("Intfnc type :   %d", ss_msg->int_type);
286*5113495bSYour Name 	spectral_dbg_line();
287*5113495bSYour Name 	spectral_debug("Spectral Data info");
288*5113495bSYour Name 	spectral_dbg_line();
289*5113495bSYour Name 	spectral_debug("data length     :   %d", p->spectral_data_len);
290*5113495bSYour Name 	spectral_debug("rssi            :   %d", p->spectral_rssi);
291*5113495bSYour Name 	spectral_debug("combined rssi   :   %d", p->spectral_combined_rssi);
292*5113495bSYour Name 	spectral_debug("upper rssi      :   %d", p->spectral_upper_rssi);
293*5113495bSYour Name 	spectral_debug("lower rssi      :   %d", p->spectral_lower_rssi);
294*5113495bSYour Name 	spectral_debug("bw info         :   %d", p->spectral_bwinfo);
295*5113495bSYour Name 	spectral_debug("timestamp       :   %d", p->spectral_tstamp);
296*5113495bSYour Name 	spectral_debug("max index       :   %d", p->spectral_max_index);
297*5113495bSYour Name 	spectral_debug("max exp         :   %d", p->spectral_max_exp);
298*5113495bSYour Name 	spectral_debug("max mag         :   %d", p->spectral_max_mag);
299*5113495bSYour Name 	spectral_debug("last timstamp   :   %d", p->spectral_last_tstamp);
300*5113495bSYour Name 	spectral_debug("upper max idx   :   %d", p->spectral_upper_max_index);
301*5113495bSYour Name 	spectral_debug("lower max idx   :   %d", p->spectral_lower_max_index);
302*5113495bSYour Name 	spectral_debug("bin power count :   %d", p->bin_pwr_count);
303*5113495bSYour Name 	spectral_dbg_line();
304*5113495bSYour Name 	spectral_debug("Classifier info");
305*5113495bSYour Name 	spectral_dbg_line();
306*5113495bSYour Name 	spectral_debug("20/40 Mode      :   %d", pc->spectral_20_40_mode);
307*5113495bSYour Name 	spectral_debug("dc index        :   %d", pc->spectral_dc_index);
308*5113495bSYour Name 	spectral_debug("dc in MHz       :   %d", pc->spectral_dc_in_mhz);
309*5113495bSYour Name 	spectral_debug("upper channel   :   %d", pc->upper_chan_in_mhz);
310*5113495bSYour Name 	spectral_debug("lower channel   :   %d", pc->lower_chan_in_mhz);
311*5113495bSYour Name 	spectral_dbg_line();
312*5113495bSYour Name 	spectral_debug("Interference info");
313*5113495bSYour Name 	spectral_dbg_line();
314*5113495bSYour Name 	spectral_debug("inter count     :   %d", pi->count);
315*5113495bSYour Name 
316*5113495bSYour Name 	for (i = 0; i < pi->count; i++) {
317*5113495bSYour Name 		spectral_debug("inter type  :   %d",
318*5113495bSYour Name 			       pi->interf[i].interf_type);
319*5113495bSYour Name 		spectral_debug("min freq    :   %d",
320*5113495bSYour Name 			       pi->interf[i].interf_min_freq);
321*5113495bSYour Name 		spectral_debug("max freq    :   %d",
322*5113495bSYour Name 			       pi->interf[i].interf_max_freq);
323*5113495bSYour Name 	}
324*5113495bSYour Name }
325*5113495bSYour Name #endif /* OPTIMIZED_SAMP_MESSAGE */
326*5113495bSYour Name 
327*5113495bSYour Name uint32_t
target_if_get_offset_swar_sec80(uint32_t channel_width)328*5113495bSYour Name target_if_get_offset_swar_sec80(uint32_t channel_width)
329*5113495bSYour Name {
330*5113495bSYour Name 	uint32_t offset = 0;
331*5113495bSYour Name 
332*5113495bSYour Name 	switch (channel_width) {
333*5113495bSYour Name 	case CH_WIDTH_20MHZ:
334*5113495bSYour Name 		offset = OFFSET_CH_WIDTH_20;
335*5113495bSYour Name 		break;
336*5113495bSYour Name 	case CH_WIDTH_40MHZ:
337*5113495bSYour Name 		offset = OFFSET_CH_WIDTH_40;
338*5113495bSYour Name 		break;
339*5113495bSYour Name 	case CH_WIDTH_80MHZ:
340*5113495bSYour Name 		offset = OFFSET_CH_WIDTH_80;
341*5113495bSYour Name 		break;
342*5113495bSYour Name 	case CH_WIDTH_160MHZ:
343*5113495bSYour Name 	case CH_WIDTH_80P80MHZ:
344*5113495bSYour Name 		offset = OFFSET_CH_WIDTH_160;
345*5113495bSYour Name 		break;
346*5113495bSYour Name 	default:
347*5113495bSYour Name 		offset = OFFSET_CH_WIDTH_80;
348*5113495bSYour Name 		break;
349*5113495bSYour Name 	}
350*5113495bSYour Name 	return offset;
351*5113495bSYour Name }
352*5113495bSYour Name 
353*5113495bSYour Name /**
354*5113495bSYour Name  * target_if_dump_summary_report_gen2() - Dump Spectral Summary Report for gen2
355*5113495bSYour Name  * @ptlv: Pointer to Spectral Phyerr TLV
356*5113495bSYour Name  * @tlvlen: length
357*5113495bSYour Name  * @is_160_format: Indicates whether information provided by HW is in altered
358*5113495bSYour Name  *                 format for 802.11ac 160/80+80 MHz support (QCA9984 onwards)
359*5113495bSYour Name  *
360*5113495bSYour Name  * Dump Spectral Summary Report for gen2
361*5113495bSYour Name  *
362*5113495bSYour Name  * Return: Success/Failure
363*5113495bSYour Name  */
364*5113495bSYour Name static int
target_if_dump_summary_report_gen2(struct spectral_phyerr_tlv_gen2 * ptlv,int tlvlen,bool is_160_format)365*5113495bSYour Name target_if_dump_summary_report_gen2(struct spectral_phyerr_tlv_gen2 *ptlv,
366*5113495bSYour Name 				   int tlvlen, bool is_160_format)
367*5113495bSYour Name {
368*5113495bSYour Name 	/*
369*5113495bSYour Name 	 * For simplicity, everything is defined as uint32_t (except one).
370*5113495bSYour Name 	 * Proper code will later use the right sizes.
371*5113495bSYour Name 	 */
372*5113495bSYour Name 
373*5113495bSYour Name 	/*
374*5113495bSYour Name 	 * For easy comparison between MDK team and OS team, the MDK script
375*5113495bSYour Name 	 * variable names have been used
376*5113495bSYour Name 	 */
377*5113495bSYour Name 
378*5113495bSYour Name 	uint32_t agc_mb_gain;
379*5113495bSYour Name 	uint32_t sscan_gidx;
380*5113495bSYour Name 	uint32_t agc_total_gain;
381*5113495bSYour Name 	uint32_t recent_rfsat;
382*5113495bSYour Name 	uint32_t ob_flag;
383*5113495bSYour Name 	uint32_t nb_mask;
384*5113495bSYour Name 	uint32_t peak_mag;
385*5113495bSYour Name 	int16_t peak_inx;
386*5113495bSYour Name 
387*5113495bSYour Name 	uint32_t ss_summary_A = 0;
388*5113495bSYour Name 	uint32_t ss_summary_B = 0;
389*5113495bSYour Name 	uint32_t ss_summary_C = 0;
390*5113495bSYour Name 	uint32_t ss_summary_D = 0;
391*5113495bSYour Name 	uint32_t ss_summary_E = 0;
392*5113495bSYour Name 	struct spectral_phyerr_hdr_gen2 *phdr =
393*5113495bSYour Name 	    (struct spectral_phyerr_hdr_gen2 *)(
394*5113495bSYour Name 		(uint8_t *)ptlv +
395*5113495bSYour Name 		sizeof(struct spectral_phyerr_tlv_gen2));
396*5113495bSYour Name 
397*5113495bSYour Name 	spectral_debug("SPECTRAL : SPECTRAL SUMMARY REPORT");
398*5113495bSYour Name 
399*5113495bSYour Name 	if (is_160_format) {
400*5113495bSYour Name 		if (tlvlen != 20) {
401*5113495bSYour Name 			spectral_err("Unexpected TLV length %d for Spectral Summary Report! Hexdump follows",
402*5113495bSYour Name 				     tlvlen);
403*5113495bSYour Name 			target_if_print_buf((uint8_t *)ptlv, tlvlen + 4);
404*5113495bSYour Name 			return -EPERM;
405*5113495bSYour Name 		}
406*5113495bSYour Name 
407*5113495bSYour Name 		/* Doing copy as the contents may not be aligned */
408*5113495bSYour Name 		qdf_mem_copy(&ss_summary_A, (uint8_t *)phdr, sizeof(int));
409*5113495bSYour Name 		qdf_mem_copy(&ss_summary_B,
410*5113495bSYour Name 			     (uint8_t *)((uint8_t *)phdr + sizeof(int)),
411*5113495bSYour Name 			     sizeof(int));
412*5113495bSYour Name 		qdf_mem_copy(&ss_summary_C,
413*5113495bSYour Name 			     (uint8_t *)((uint8_t *)phdr + 2 * sizeof(int)),
414*5113495bSYour Name 			     sizeof(int));
415*5113495bSYour Name 		qdf_mem_copy(&ss_summary_D,
416*5113495bSYour Name 			     (uint8_t *)((uint8_t *)phdr + 3 * sizeof(int)),
417*5113495bSYour Name 			     sizeof(int));
418*5113495bSYour Name 		qdf_mem_copy(&ss_summary_E,
419*5113495bSYour Name 			     (uint8_t *)((uint8_t *)phdr + 4 * sizeof(int)),
420*5113495bSYour Name 			     sizeof(int));
421*5113495bSYour Name 
422*5113495bSYour Name 		/*
423*5113495bSYour Name 		 * The following is adapted from MDK scripts for
424*5113495bSYour Name 		 * easier comparability
425*5113495bSYour Name 		 */
426*5113495bSYour Name 
427*5113495bSYour Name 		recent_rfsat = ((ss_summary_A >> 8) & 0x1);
428*5113495bSYour Name 		sscan_gidx = (ss_summary_A & 0xff);
429*5113495bSYour Name 		spectral_debug("sscan_gidx=%d, is_recent_rfsat=%d",
430*5113495bSYour Name 			       sscan_gidx, recent_rfsat);
431*5113495bSYour Name 
432*5113495bSYour Name 		/* First segment */
433*5113495bSYour Name 		agc_mb_gain = ((ss_summary_B >> 10) & 0x7f);
434*5113495bSYour Name 		agc_total_gain = (ss_summary_B & 0x3ff);
435*5113495bSYour Name 		nb_mask = ((ss_summary_C >> 22) & 0xff);
436*5113495bSYour Name 		ob_flag = ((ss_summary_B >> 17) & 0x1);
437*5113495bSYour Name 		peak_inx = (ss_summary_C & 0xfff);
438*5113495bSYour Name 		if (peak_inx > 2047)
439*5113495bSYour Name 			peak_inx = peak_inx - 4096;
440*5113495bSYour Name 		peak_mag = ((ss_summary_C >> 12) & 0x3ff);
441*5113495bSYour Name 
442*5113495bSYour Name 		spectral_debug("agc_total_gain_segid0 = 0x%.2x, agc_mb_gain_segid0=%d",
443*5113495bSYour Name 			       agc_total_gain, agc_mb_gain);
444*5113495bSYour Name 		spectral_debug("nb_mask_segid0 = 0x%.2x, ob_flag_segid0=%d, peak_index_segid0=%d, peak_mag_segid0=%d",
445*5113495bSYour Name 			       nb_mask, ob_flag, peak_inx, peak_mag);
446*5113495bSYour Name 
447*5113495bSYour Name 		/* Second segment */
448*5113495bSYour Name 		agc_mb_gain = ((ss_summary_D >> 10) & 0x7f);
449*5113495bSYour Name 		agc_total_gain = (ss_summary_D & 0x3ff);
450*5113495bSYour Name 		nb_mask = ((ss_summary_E >> 22) & 0xff);
451*5113495bSYour Name 		ob_flag = ((ss_summary_D >> 17) & 0x1);
452*5113495bSYour Name 		peak_inx = (ss_summary_E & 0xfff);
453*5113495bSYour Name 		if (peak_inx > 2047)
454*5113495bSYour Name 			peak_inx = peak_inx - 4096;
455*5113495bSYour Name 		peak_mag = ((ss_summary_E >> 12) & 0x3ff);
456*5113495bSYour Name 
457*5113495bSYour Name 		spectral_debug("agc_total_gain_segid1 = 0x%.2x, agc_mb_gain_segid1=%d",
458*5113495bSYour Name 			       agc_total_gain, agc_mb_gain);
459*5113495bSYour Name 		spectral_debug("nb_mask_segid1 = 0x%.2x, ob_flag_segid1=%d, peak_index_segid1=%d, peak_mag_segid1=%d",
460*5113495bSYour Name 			       nb_mask, ob_flag, peak_inx, peak_mag);
461*5113495bSYour Name 	} else {
462*5113495bSYour Name 		if (tlvlen != 8) {
463*5113495bSYour Name 			spectral_err("Unexpected TLV length %d for Spectral Summary Report! Hexdump follows",
464*5113495bSYour Name 				     tlvlen);
465*5113495bSYour Name 			target_if_print_buf((uint8_t *)ptlv, tlvlen + 4);
466*5113495bSYour Name 			return -EPERM;
467*5113495bSYour Name 		}
468*5113495bSYour Name 
469*5113495bSYour Name 		/* Doing copy as the contents may not be aligned */
470*5113495bSYour Name 		qdf_mem_copy(&ss_summary_A, (uint8_t *)phdr, sizeof(int));
471*5113495bSYour Name 		qdf_mem_copy(&ss_summary_B,
472*5113495bSYour Name 			     (uint8_t *)((uint8_t *)phdr + sizeof(int)),
473*5113495bSYour Name 			     sizeof(int));
474*5113495bSYour Name 
475*5113495bSYour Name 		nb_mask = ((ss_summary_B >> 22) & 0xff);
476*5113495bSYour Name 		ob_flag = ((ss_summary_B >> 30) & 0x1);
477*5113495bSYour Name 		peak_inx = (ss_summary_B & 0xfff);
478*5113495bSYour Name 
479*5113495bSYour Name 		if (peak_inx > 2047)
480*5113495bSYour Name 			peak_inx = peak_inx - 4096;
481*5113495bSYour Name 
482*5113495bSYour Name 		peak_mag = ((ss_summary_B >> 12) & 0x3ff);
483*5113495bSYour Name 		agc_mb_gain = ((ss_summary_A >> 24) & 0x7f);
484*5113495bSYour Name 		agc_total_gain = (ss_summary_A & 0x3ff);
485*5113495bSYour Name 		sscan_gidx = ((ss_summary_A >> 16) & 0xff);
486*5113495bSYour Name 		recent_rfsat = ((ss_summary_B >> 31) & 0x1);
487*5113495bSYour Name 
488*5113495bSYour Name 		spectral_debug("nb_mask = 0x%.2x, ob_flag=%d, peak_index=%d, peak_mag=%d, agc_mb_gain=%d, agc_total_gain=%d, sscan_gidx=%d, recent_rfsat=%d",
489*5113495bSYour Name 			       nb_mask, ob_flag, peak_inx, peak_mag,
490*5113495bSYour Name 			       agc_mb_gain, agc_total_gain, sscan_gidx,
491*5113495bSYour Name 			       recent_rfsat);
492*5113495bSYour Name 	}
493*5113495bSYour Name 
494*5113495bSYour Name 	return 0;
495*5113495bSYour Name }
496*5113495bSYour Name 
497*5113495bSYour Name /**
498*5113495bSYour Name  * target_if_process_sfft_report_gen2() - Process Search FFT Report
499*5113495bSYour Name  * @ptlv: Pointer to Spectral Phyerr TLV
500*5113495bSYour Name  * @tlvlen: length
501*5113495bSYour Name  * @p_fft_info: Pointer to search fft info
502*5113495bSYour Name  *
503*5113495bSYour Name  * Dump Spectral Summary Report for gen2
504*5113495bSYour Name  *
505*5113495bSYour Name  * Return: Success/Failure
506*5113495bSYour Name  */
507*5113495bSYour Name static int
target_if_process_sfft_report_gen2(struct spectral_phyerr_tlv_gen2 * ptlv,int tlvlen,struct spectral_search_fft_info_gen2 * p_fft_info)508*5113495bSYour Name target_if_process_sfft_report_gen2(
509*5113495bSYour Name 	struct spectral_phyerr_tlv_gen2 *ptlv,
510*5113495bSYour Name 	int tlvlen,
511*5113495bSYour Name 	struct spectral_search_fft_info_gen2 *p_fft_info)
512*5113495bSYour Name {
513*5113495bSYour Name 	/*
514*5113495bSYour Name 	 * For simplicity, everything is defined as uint32_t (except one).
515*5113495bSYour Name 	 * Proper code will later use the right sizes.
516*5113495bSYour Name 	 */
517*5113495bSYour Name 	/*
518*5113495bSYour Name 	 * For easy comparison between MDK team and OS team, the MDK script
519*5113495bSYour Name 	 * variable names have been used
520*5113495bSYour Name 	 */
521*5113495bSYour Name 	uint32_t relpwr_db;
522*5113495bSYour Name 	uint32_t num_str_bins_ib;
523*5113495bSYour Name 	uint32_t base_pwr;
524*5113495bSYour Name 	uint32_t total_gain_info;
525*5113495bSYour Name 
526*5113495bSYour Name 	uint32_t fft_chn_idx;
527*5113495bSYour Name 	int16_t peak_inx;
528*5113495bSYour Name 	uint32_t avgpwr_db;
529*5113495bSYour Name 	uint32_t peak_mag;
530*5113495bSYour Name 
531*5113495bSYour Name 	uint32_t fft_summary_A = 0;
532*5113495bSYour Name 	uint32_t fft_summary_B = 0;
533*5113495bSYour Name 	uint8_t *tmp = (uint8_t *)ptlv;
534*5113495bSYour Name 	struct spectral_phyerr_hdr_gen2 *phdr =
535*5113495bSYour Name 	    (struct spectral_phyerr_hdr_gen2 *)(
536*5113495bSYour Name 		tmp +
537*5113495bSYour Name 		sizeof(struct spectral_phyerr_tlv_gen2));
538*5113495bSYour Name 
539*5113495bSYour Name 	/* Relook this */
540*5113495bSYour Name 	if (tlvlen < 8) {
541*5113495bSYour Name 		spectral_err("Unexpected TLV length %d for Spectral Summary Report! Hexdump follows",
542*5113495bSYour Name 			     tlvlen);
543*5113495bSYour Name 		target_if_print_buf((uint8_t *)ptlv, tlvlen + 4);
544*5113495bSYour Name 		return -EPERM;
545*5113495bSYour Name 	}
546*5113495bSYour Name 
547*5113495bSYour Name 	/* Doing copy as the contents may not be aligned */
548*5113495bSYour Name 	qdf_mem_copy(&fft_summary_A, (uint8_t *)phdr, sizeof(int));
549*5113495bSYour Name 	qdf_mem_copy(&fft_summary_B,
550*5113495bSYour Name 		     (uint8_t *)((uint8_t *)phdr + sizeof(int)),
551*5113495bSYour Name 		     sizeof(int));
552*5113495bSYour Name 
553*5113495bSYour Name 	relpwr_db = ((fft_summary_B >> 26) & 0x3f);
554*5113495bSYour Name 	num_str_bins_ib = fft_summary_B & 0xff;
555*5113495bSYour Name 	base_pwr = ((fft_summary_A >> 14) & 0x1ff);
556*5113495bSYour Name 	total_gain_info = ((fft_summary_A >> 23) & 0x1ff);
557*5113495bSYour Name 
558*5113495bSYour Name 	fft_chn_idx = ((fft_summary_A >> 12) & 0x3);
559*5113495bSYour Name 	peak_inx = fft_summary_A & 0xfff;
560*5113495bSYour Name 
561*5113495bSYour Name 	if (peak_inx > 2047)
562*5113495bSYour Name 		peak_inx = peak_inx - 4096;
563*5113495bSYour Name 
564*5113495bSYour Name 	avgpwr_db = ((fft_summary_B >> 18) & 0xff);
565*5113495bSYour Name 	peak_mag = ((fft_summary_B >> 8) & 0x3ff);
566*5113495bSYour Name 
567*5113495bSYour Name 	/* Populate the Search FFT Info */
568*5113495bSYour Name 	if (p_fft_info) {
569*5113495bSYour Name 		p_fft_info->relpwr_db = relpwr_db;
570*5113495bSYour Name 		p_fft_info->num_str_bins_ib = num_str_bins_ib;
571*5113495bSYour Name 		p_fft_info->base_pwr = base_pwr;
572*5113495bSYour Name 		p_fft_info->total_gain_info = total_gain_info;
573*5113495bSYour Name 		p_fft_info->fft_chn_idx = fft_chn_idx;
574*5113495bSYour Name 		p_fft_info->peak_inx = peak_inx;
575*5113495bSYour Name 		p_fft_info->avgpwr_db = avgpwr_db;
576*5113495bSYour Name 		p_fft_info->peak_mag = peak_mag;
577*5113495bSYour Name 	}
578*5113495bSYour Name 
579*5113495bSYour Name 	return 0;
580*5113495bSYour Name }
581*5113495bSYour Name 
582*5113495bSYour Name /**
583*5113495bSYour Name  * target_if_dump_adc_report_gen2() - Dump ADC Reports for gen2
584*5113495bSYour Name  * @ptlv: Pointer to Spectral Phyerr TLV
585*5113495bSYour Name  * @tlvlen: length
586*5113495bSYour Name  *
587*5113495bSYour Name  * Dump ADC Reports for gen2
588*5113495bSYour Name  *
589*5113495bSYour Name  * Return: Success/Failure
590*5113495bSYour Name  */
591*5113495bSYour Name static int
target_if_dump_adc_report_gen2(struct spectral_phyerr_tlv_gen2 * ptlv,int tlvlen)592*5113495bSYour Name target_if_dump_adc_report_gen2(
593*5113495bSYour Name 	struct spectral_phyerr_tlv_gen2 *ptlv, int tlvlen)
594*5113495bSYour Name {
595*5113495bSYour Name 	int i;
596*5113495bSYour Name 	uint32_t *pdata;
597*5113495bSYour Name 	uint32_t data;
598*5113495bSYour Name 
599*5113495bSYour Name 	/*
600*5113495bSYour Name 	 * For simplicity, everything is defined as uint32_t (except one).
601*5113495bSYour Name 	 * Proper code will later use the right sizes.
602*5113495bSYour Name 	 */
603*5113495bSYour Name 	uint32_t samp_fmt;
604*5113495bSYour Name 	uint32_t chn_idx;
605*5113495bSYour Name 	uint32_t recent_rfsat;
606*5113495bSYour Name 	uint32_t agc_mb_gain;
607*5113495bSYour Name 	uint32_t agc_total_gain;
608*5113495bSYour Name 
609*5113495bSYour Name 	uint32_t adc_summary = 0;
610*5113495bSYour Name 
611*5113495bSYour Name 	uint8_t *ptmp = (uint8_t *)ptlv;
612*5113495bSYour Name 
613*5113495bSYour Name 	spectral_debug("SPECTRAL : ADC REPORT");
614*5113495bSYour Name 
615*5113495bSYour Name 	/* Relook this */
616*5113495bSYour Name 	if (tlvlen < 4) {
617*5113495bSYour Name 		spectral_err("Unexpected TLV length %d for ADC Report! Hexdump follows",
618*5113495bSYour Name 			     tlvlen);
619*5113495bSYour Name 		target_if_print_buf((uint8_t *)ptlv, tlvlen + 4);
620*5113495bSYour Name 		return -EPERM;
621*5113495bSYour Name 	}
622*5113495bSYour Name 
623*5113495bSYour Name 	qdf_mem_copy(&adc_summary, (uint8_t *)(ptlv + 4), sizeof(int));
624*5113495bSYour Name 
625*5113495bSYour Name 	samp_fmt = ((adc_summary >> 28) & 0x1);
626*5113495bSYour Name 	chn_idx = ((adc_summary >> 24) & 0x3);
627*5113495bSYour Name 	recent_rfsat = ((adc_summary >> 23) & 0x1);
628*5113495bSYour Name 	agc_mb_gain = ((adc_summary >> 16) & 0x7f);
629*5113495bSYour Name 	agc_total_gain = adc_summary & 0x3ff;
630*5113495bSYour Name 
631*5113495bSYour Name 	spectral_debug("samp_fmt= %u, chn_idx= %u, recent_rfsat= %u, agc_mb_gain=%u agc_total_gain=%u",
632*5113495bSYour Name 		       samp_fmt, chn_idx, recent_rfsat, agc_mb_gain,
633*5113495bSYour Name 		       agc_total_gain);
634*5113495bSYour Name 
635*5113495bSYour Name 	for (i = 0; i < (tlvlen / 4); i++) {
636*5113495bSYour Name 		pdata = (uint32_t *)(ptmp + 4 + i * 4);
637*5113495bSYour Name 		data = *pdata;
638*5113495bSYour Name 
639*5113495bSYour Name 		/* Interpreting capture format 1 */
640*5113495bSYour Name 		if (1) {
641*5113495bSYour Name 			uint8_t i1;
642*5113495bSYour Name 			uint8_t q1;
643*5113495bSYour Name 			uint8_t i2;
644*5113495bSYour Name 			uint8_t q2;
645*5113495bSYour Name 			int8_t si1;
646*5113495bSYour Name 			int8_t sq1;
647*5113495bSYour Name 			int8_t si2;
648*5113495bSYour Name 			int8_t sq2;
649*5113495bSYour Name 
650*5113495bSYour Name 			i1 = data & 0xff;
651*5113495bSYour Name 			q1 = (data >> 8) & 0xff;
652*5113495bSYour Name 			i2 = (data >> 16) & 0xff;
653*5113495bSYour Name 			q2 = (data >> 24) & 0xff;
654*5113495bSYour Name 
655*5113495bSYour Name 			if (i1 > 127)
656*5113495bSYour Name 				si1 = i1 - 256;
657*5113495bSYour Name 			else
658*5113495bSYour Name 				si1 = i1;
659*5113495bSYour Name 
660*5113495bSYour Name 			if (q1 > 127)
661*5113495bSYour Name 				sq1 = q1 - 256;
662*5113495bSYour Name 			else
663*5113495bSYour Name 				sq1 = q1;
664*5113495bSYour Name 
665*5113495bSYour Name 			if (i2 > 127)
666*5113495bSYour Name 				si2 = i2 - 256;
667*5113495bSYour Name 			else
668*5113495bSYour Name 				si2 = i2;
669*5113495bSYour Name 
670*5113495bSYour Name 			if (q2 > 127)
671*5113495bSYour Name 				sq2 = q2 - 256;
672*5113495bSYour Name 			else
673*5113495bSYour Name 				sq2 = q2;
674*5113495bSYour Name 
675*5113495bSYour Name 			spectral_debug("SPECTRAL ADC : Interpreting capture format 1");
676*5113495bSYour Name 			spectral_debug("adc_data_format_1 # %d %d %d",
677*5113495bSYour Name 				       2 * i, si1, sq1);
678*5113495bSYour Name 			spectral_debug("adc_data_format_1 # %d %d %d",
679*5113495bSYour Name 				       2 * i + 1, si2, sq2);
680*5113495bSYour Name 		}
681*5113495bSYour Name 
682*5113495bSYour Name 		/* Interpreting capture format 0 */
683*5113495bSYour Name 		if (1) {
684*5113495bSYour Name 			uint16_t i1;
685*5113495bSYour Name 			uint16_t q1;
686*5113495bSYour Name 			int16_t si1;
687*5113495bSYour Name 			int16_t sq1;
688*5113495bSYour Name 
689*5113495bSYour Name 			i1 = data & 0xffff;
690*5113495bSYour Name 			q1 = (data >> 16) & 0xffff;
691*5113495bSYour Name 			if (i1 > 32767)
692*5113495bSYour Name 				si1 = i1 - 65536;
693*5113495bSYour Name 			else
694*5113495bSYour Name 				si1 = i1;
695*5113495bSYour Name 
696*5113495bSYour Name 			if (q1 > 32767)
697*5113495bSYour Name 				sq1 = q1 - 65536;
698*5113495bSYour Name 			else
699*5113495bSYour Name 				sq1 = q1;
700*5113495bSYour Name 			spectral_debug("SPECTRAL ADC : Interpreting capture format 0");
701*5113495bSYour Name 			spectral_debug("adc_data_format_2 # %d %d %d",
702*5113495bSYour Name 				       i, si1, sq1);
703*5113495bSYour Name 		}
704*5113495bSYour Name 	}
705*5113495bSYour Name 
706*5113495bSYour Name 	spectral_debug("\n");
707*5113495bSYour Name 
708*5113495bSYour Name 	return 0;
709*5113495bSYour Name }
710*5113495bSYour Name 
711*5113495bSYour Name /**
712*5113495bSYour Name  * target_if_dump_sfft_report_gen2() - Process Search FFT Report for gen2
713*5113495bSYour Name  * @ptlv: Pointer to Spectral Phyerr TLV
714*5113495bSYour Name  * @tlvlen: length
715*5113495bSYour Name  * @is_160_format: Indicates 160 format
716*5113495bSYour Name  *
717*5113495bSYour Name  * Process Search FFT Report for gen2
718*5113495bSYour Name  *
719*5113495bSYour Name  * Return: Success/Failure
720*5113495bSYour Name  */
721*5113495bSYour Name static int
target_if_dump_sfft_report_gen2(struct spectral_phyerr_tlv_gen2 * ptlv,int tlvlen,bool is_160_format)722*5113495bSYour Name target_if_dump_sfft_report_gen2(struct spectral_phyerr_tlv_gen2 *ptlv,
723*5113495bSYour Name 				int tlvlen, bool is_160_format)
724*5113495bSYour Name {
725*5113495bSYour Name 	int i;
726*5113495bSYour Name 	uint32_t fft_mag;
727*5113495bSYour Name 
728*5113495bSYour Name 	/*
729*5113495bSYour Name 	 * For simplicity, everything is defined as uint32_t (except one).
730*5113495bSYour Name 	 * Proper code will later use the right sizes.
731*5113495bSYour Name 	 */
732*5113495bSYour Name 	/*
733*5113495bSYour Name 	 * For easy comparison between MDK team and OS team, the MDK script
734*5113495bSYour Name 	 * variable names have been used
735*5113495bSYour Name 	 */
736*5113495bSYour Name 	uint32_t relpwr_db;
737*5113495bSYour Name 	uint32_t num_str_bins_ib;
738*5113495bSYour Name 	uint32_t base_pwr;
739*5113495bSYour Name 	uint32_t total_gain_info;
740*5113495bSYour Name 
741*5113495bSYour Name 	uint32_t fft_chn_idx;
742*5113495bSYour Name 	int16_t peak_inx;
743*5113495bSYour Name 	uint32_t avgpwr_db;
744*5113495bSYour Name 	uint32_t peak_mag;
745*5113495bSYour Name 	uint8_t segid;
746*5113495bSYour Name 
747*5113495bSYour Name 	uint32_t fft_summary_A = 0;
748*5113495bSYour Name 	uint32_t fft_summary_B = 0;
749*5113495bSYour Name 	uint32_t fft_summary_C = 0;
750*5113495bSYour Name 	uint8_t *tmp = (uint8_t *)ptlv;
751*5113495bSYour Name 	struct spectral_phyerr_hdr_gen2 *phdr =
752*5113495bSYour Name 	    (struct spectral_phyerr_hdr_gen2 *)(
753*5113495bSYour Name 		tmp +
754*5113495bSYour Name 		sizeof(struct spectral_phyerr_tlv_gen2));
755*5113495bSYour Name 	uint32_t segid_skiplen = 0;
756*5113495bSYour Name 
757*5113495bSYour Name 	if (is_160_format)
758*5113495bSYour Name 		segid_skiplen = sizeof(SPECTRAL_SEGID_INFO);
759*5113495bSYour Name 
760*5113495bSYour Name 	spectral_debug("SPECTRAL : SEARCH FFT REPORT");
761*5113495bSYour Name 
762*5113495bSYour Name 	/* Relook this */
763*5113495bSYour Name 	if (tlvlen < (8 + segid_skiplen)) {
764*5113495bSYour Name 		spectral_err("Unexpected TLV length %d for Spectral Summary Report! Hexdump follows",
765*5113495bSYour Name 			     tlvlen);
766*5113495bSYour Name 		target_if_print_buf((uint8_t *)ptlv, tlvlen + 4);
767*5113495bSYour Name 		return -EPERM;
768*5113495bSYour Name 	}
769*5113495bSYour Name 
770*5113495bSYour Name 	/* Doing copy as the contents may not be aligned */
771*5113495bSYour Name 	qdf_mem_copy(&fft_summary_A, (uint8_t *)phdr, sizeof(int));
772*5113495bSYour Name 	qdf_mem_copy(&fft_summary_B,
773*5113495bSYour Name 		     (uint8_t *)((uint8_t *)phdr + sizeof(int)),
774*5113495bSYour Name 		     sizeof(int));
775*5113495bSYour Name 	if (is_160_format)
776*5113495bSYour Name 		qdf_mem_copy(&fft_summary_C,
777*5113495bSYour Name 			     (uint8_t *)((uint8_t *)phdr + 2 * sizeof(int)),
778*5113495bSYour Name 			     sizeof(int));
779*5113495bSYour Name 
780*5113495bSYour Name 	relpwr_db = ((fft_summary_B >> 26) & 0x3f);
781*5113495bSYour Name 	num_str_bins_ib = fft_summary_B & 0xff;
782*5113495bSYour Name 	base_pwr = ((fft_summary_A >> 14) & 0x1ff);
783*5113495bSYour Name 	total_gain_info = ((fft_summary_A >> 23) & 0x1ff);
784*5113495bSYour Name 
785*5113495bSYour Name 	fft_chn_idx = ((fft_summary_A >> 12) & 0x3);
786*5113495bSYour Name 	peak_inx = fft_summary_A & 0xfff;
787*5113495bSYour Name 
788*5113495bSYour Name 	if (peak_inx > 2047)
789*5113495bSYour Name 		peak_inx = peak_inx - 4096;
790*5113495bSYour Name 
791*5113495bSYour Name 	avgpwr_db = ((fft_summary_B >> 18) & 0xff);
792*5113495bSYour Name 	peak_mag = ((fft_summary_B >> 8) & 0x3ff);
793*5113495bSYour Name 
794*5113495bSYour Name 	spectral_debug("Header A = 0x%x Header B = 0x%x",
795*5113495bSYour Name 		       phdr->hdr_a, phdr->hdr_b);
796*5113495bSYour Name 	spectral_debug("Base Power= 0x%x, Total Gain= %d, relpwr_db=%d, num_str_bins_ib=%d fft_chn_idx=%d peak_inx=%d avgpwr_db=%d peak_mag=%d",
797*5113495bSYour Name 		       base_pwr, total_gain_info, relpwr_db, num_str_bins_ib,
798*5113495bSYour Name 		       fft_chn_idx, peak_inx, avgpwr_db, peak_mag);
799*5113495bSYour Name 	if (is_160_format) {
800*5113495bSYour Name 		segid = fft_summary_C & 0x1;
801*5113495bSYour Name 		spectral_debug("Segment ID: %hhu", segid);
802*5113495bSYour Name 	}
803*5113495bSYour Name 
804*5113495bSYour Name 	spectral_debug("FFT bins:");
805*5113495bSYour Name 	for (i = 0; i < (tlvlen - 8 - segid_skiplen); i++) {
806*5113495bSYour Name 		fft_mag = ((uint8_t *)ptlv)[12 + segid_skiplen + i];
807*5113495bSYour Name 		spectral_debug("%d %d, ", i, fft_mag);
808*5113495bSYour Name 	}
809*5113495bSYour Name 
810*5113495bSYour Name 	spectral_debug("\n");
811*5113495bSYour Name 
812*5113495bSYour Name 	return 0;
813*5113495bSYour Name }
814*5113495bSYour Name 
815*5113495bSYour Name #ifndef OPTIMIZED_SAMP_MESSAGE
816*5113495bSYour Name #ifdef SPECTRAL_DEBUG_SAMP_MSG
817*5113495bSYour Name /**
818*5113495bSYour Name  * target_if_spectral_log_SAMP_param() - Log SAMP parameters
819*5113495bSYour Name  * @params: Reference to target_if_samp_msg_params
820*5113495bSYour Name  *
821*5113495bSYour Name  * API to log spectral SAMP message parameters
822*5113495bSYour Name  *
823*5113495bSYour Name  * Return: None
824*5113495bSYour Name  */
825*5113495bSYour Name static void
target_if_spectral_log_SAMP_param(struct target_if_samp_msg_params * params)826*5113495bSYour Name target_if_spectral_log_SAMP_param(struct target_if_samp_msg_params *params)
827*5113495bSYour Name {
828*5113495bSYour Name 	target_if_dbg_print_samp_param(params);
829*5113495bSYour Name }
830*5113495bSYour Name 
831*5113495bSYour Name #else
832*5113495bSYour Name static void
target_if_spectral_log_SAMP_param(struct target_if_samp_msg_params * params)833*5113495bSYour Name target_if_spectral_log_SAMP_param(struct target_if_samp_msg_params *params)
834*5113495bSYour Name {
835*5113495bSYour Name }
836*5113495bSYour Name #endif
837*5113495bSYour Name #endif /* OPTIMIZED_SAMP_MESSAGE */
838*5113495bSYour Name 
839*5113495bSYour Name #ifdef OPTIMIZED_SAMP_MESSAGE
840*5113495bSYour Name /**
841*5113495bSYour Name  * target_if_spectral_unify_cfreq_format() - Unify the cfreq representations.
842*5113495bSYour Name  * @spectral: Pointer to target_if spectral internal structure
843*5113495bSYour Name  * @cfreq1: cfreq1 value received in the Spectral report
844*5113495bSYour Name  * @cfreq2: cfreq2 value received in the Spectral report
845*5113495bSYour Name  * @pri20_freq: Primary 20MHz frequency of operation
846*5113495bSYour Name  * @ch_width: channel width. If the center frequencies are of operating channel,
847*5113495bSYour Name  * pass the operating channel width, else pass the sscan channel width.
848*5113495bSYour Name  * @smode: Spectral scan mode
849*5113495bSYour Name  *
850*5113495bSYour Name  * This API converts the cfreq1 and cfreq2 representations as follows.
851*5113495bSYour Name  * For a contiguous channel, cfreq1 will represent the center of the entire
852*5113495bSYour Name  * span and cfreq2 will be 0. For a discontiguous channel like 80p80, cfreq1
853*5113495bSYour Name  * will represent the center of primary segment whereas cfreq2 will
854*5113495bSYour Name  * represent the center of secondary segment.
855*5113495bSYour Name  *
856*5113495bSYour Name  * Return: Success/Failure
857*5113495bSYour Name  */
858*5113495bSYour Name static QDF_STATUS
target_if_spectral_unify_cfreq_format(struct target_if_spectral * spectral,uint32_t * cfreq1,uint32_t * cfreq2,uint32_t pri20_freq,enum phy_ch_width ch_width,enum spectral_scan_mode smode)859*5113495bSYour Name target_if_spectral_unify_cfreq_format(struct target_if_spectral *spectral,
860*5113495bSYour Name 				      uint32_t *cfreq1, uint32_t *cfreq2,
861*5113495bSYour Name 				      uint32_t pri20_freq,
862*5113495bSYour Name 				      enum phy_ch_width ch_width,
863*5113495bSYour Name 				      enum spectral_scan_mode smode)
864*5113495bSYour Name 
865*5113495bSYour Name {
866*5113495bSYour Name 	uint32_t reported_cfreq1, reported_cfreq2;
867*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
868*5113495bSYour Name 
869*5113495bSYour Name 	if (!spectral) {
870*5113495bSYour Name 		spectral_err_rl("Spectral LMAC object is null");
871*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
872*5113495bSYour Name 	}
873*5113495bSYour Name 	if (!spectral->pdev_obj) {
874*5113495bSYour Name 		spectral_err_rl("Spectral PDEV is null");
875*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
876*5113495bSYour Name 	}
877*5113495bSYour Name 
878*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(spectral->pdev_obj);
879*5113495bSYour Name 	if (!psoc) {
880*5113495bSYour Name 		spectral_err_rl("psoc is null");
881*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
882*5113495bSYour Name 	}
883*5113495bSYour Name 
884*5113495bSYour Name 	reported_cfreq1 = *cfreq1;
885*5113495bSYour Name 	reported_cfreq2 = *cfreq2;
886*5113495bSYour Name 
887*5113495bSYour Name 	if (ch_width == CH_WIDTH_160MHZ &&
888*5113495bSYour Name 	    spectral->rparams.fragmentation_160[smode]) {
889*5113495bSYour Name 		/* cfreq should be 0 for 160MHz as it is contiguous */
890*5113495bSYour Name 		*cfreq2 = 0;
891*5113495bSYour Name 
892*5113495bSYour Name 		/**
893*5113495bSYour Name 		 * For gen3 chipsets that use fragmentation, cfreq1 is center of
894*5113495bSYour Name 		 * pri80, and cfreq2 is center of sec80. Averaging them gives
895*5113495bSYour Name 		 * the center of the 160MHz span.
896*5113495bSYour Name 		 * Whereas gen2 chipsets report the center of the 160MHz span in
897*5113495bSYour Name 		 * cfreq2 itself.
898*5113495bSYour Name 		 */
899*5113495bSYour Name 		if (spectral->spectral_gen == SPECTRAL_GEN3)
900*5113495bSYour Name 			*cfreq1 = (reported_cfreq1 + reported_cfreq2) >> 1;
901*5113495bSYour Name 		else
902*5113495bSYour Name 			*cfreq1 = reported_cfreq2;
903*5113495bSYour Name 	} else if (ch_width == CH_WIDTH_80P80MHZ &&
904*5113495bSYour Name 		   wlan_psoc_nif_fw_ext_cap_get(
905*5113495bSYour Name 		   psoc, WLAN_SOC_RESTRICTED_80P80_SUPPORT)) {
906*5113495bSYour Name 			/* In restricted 80p80 case */
907*5113495bSYour Name 			const struct bonded_channel_freq
908*5113495bSYour Name 					*bonded_chan_ptr = NULL;
909*5113495bSYour Name 			enum channel_state state;
910*5113495bSYour Name 
911*5113495bSYour Name 			/* Get the 80MHz channel containing the pri20 freq */
912*5113495bSYour Name 			state =
913*5113495bSYour Name 			    wlan_reg_get_5g_bonded_channel_and_state_for_pwrmode
914*5113495bSYour Name 				(spectral->pdev_obj, pri20_freq, CH_WIDTH_80MHZ,
915*5113495bSYour Name 				 &bonded_chan_ptr, REG_CURRENT_PWR_MODE,
916*5113495bSYour Name 				 NO_SCHANS_PUNC);
917*5113495bSYour Name 
918*5113495bSYour Name 			if (state == CHANNEL_STATE_DISABLE ||
919*5113495bSYour Name 			    state == CHANNEL_STATE_INVALID) {
920*5113495bSYour Name 				spectral_err_rl("Channel state is disable or invalid");
921*5113495bSYour Name 				return QDF_STATUS_E_FAILURE;
922*5113495bSYour Name 			}
923*5113495bSYour Name 
924*5113495bSYour Name 			if (!bonded_chan_ptr) {
925*5113495bSYour Name 				spectral_err_rl("Bonded channel is not found");
926*5113495bSYour Name 				return QDF_STATUS_E_FAILURE;
927*5113495bSYour Name 			}
928*5113495bSYour Name 
929*5113495bSYour Name 			/* cfreq1 is the center of the pri80 segment */
930*5113495bSYour Name 			*cfreq1 = (bonded_chan_ptr->start_freq +
931*5113495bSYour Name 				   bonded_chan_ptr->end_freq) >> 1;
932*5113495bSYour Name 
933*5113495bSYour Name 			/**
934*5113495bSYour Name 			 * cfreq2 is 85MHz away from cfreq1. Whether it is
935*5113495bSYour Name 			 * higher or lower depends on pri20_freq's relationship
936*5113495bSYour Name 			 * with the reported center frequency.
937*5113495bSYour Name 			 */
938*5113495bSYour Name 			if (pri20_freq < reported_cfreq1)
939*5113495bSYour Name 				*cfreq2 = *cfreq1 + FREQ_OFFSET_85MHZ;
940*5113495bSYour Name 			else
941*5113495bSYour Name 				*cfreq2 = *cfreq1 - FREQ_OFFSET_85MHZ;
942*5113495bSYour Name 	} else {
943*5113495bSYour Name 		/* All other cases are reporting the cfreq properly */
944*5113495bSYour Name 		*cfreq1 = reported_cfreq1;
945*5113495bSYour Name 		*cfreq2 = reported_cfreq2;
946*5113495bSYour Name 	}
947*5113495bSYour Name 
948*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
949*5113495bSYour Name }
950*5113495bSYour Name 
951*5113495bSYour Name /**
952*5113495bSYour Name  * target_if_populate_det_start_end_freqs() - Populate the start and end
953*5113495bSYour Name  * frequencies, on per-detector level.
954*5113495bSYour Name  * @spectral: Pointer to target_if spectral internal structure
955*5113495bSYour Name  * @smode: Spectral scan mode
956*5113495bSYour Name  *
957*5113495bSYour Name  * Populate the start and end frequencies, on per-detector level.
958*5113495bSYour Name  *
959*5113495bSYour Name  * Return: Success/Failure
960*5113495bSYour Name  */
961*5113495bSYour Name static QDF_STATUS
target_if_populate_det_start_end_freqs(struct target_if_spectral * spectral,enum spectral_scan_mode smode)962*5113495bSYour Name target_if_populate_det_start_end_freqs(struct target_if_spectral *spectral,
963*5113495bSYour Name 				       enum spectral_scan_mode smode)
964*5113495bSYour Name {
965*5113495bSYour Name 	struct per_session_report_info *rpt_info;
966*5113495bSYour Name 	struct per_session_det_map *det_map;
967*5113495bSYour Name 	struct per_session_dest_det_info *dest_det_info;
968*5113495bSYour Name 	enum phy_ch_width ch_width;
969*5113495bSYour Name 	struct sscan_detector_list *detector_list;
970*5113495bSYour Name 	bool is_fragmentation_160;
971*5113495bSYour Name 	uint8_t det;
972*5113495bSYour Name 	uint32_t cfreq;
973*5113495bSYour Name 	uint32_t start_end_freq_arr[2];
974*5113495bSYour Name 
975*5113495bSYour Name 	if (!spectral) {
976*5113495bSYour Name 		spectral_err_rl("Spectral LMAC object is null");
977*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
978*5113495bSYour Name 	}
979*5113495bSYour Name 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
980*5113495bSYour Name 		spectral_err_rl("Invalid Spectral mode");
981*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
982*5113495bSYour Name 	}
983*5113495bSYour Name 
984*5113495bSYour Name 	qdf_spin_lock_bh(&spectral->session_report_info_lock);
985*5113495bSYour Name 
986*5113495bSYour Name 	ch_width = spectral->report_info[smode].sscan_bw;
987*5113495bSYour Name 	is_fragmentation_160 = spectral->rparams.fragmentation_160[smode];
988*5113495bSYour Name 
989*5113495bSYour Name 	rpt_info = &spectral->report_info[smode];
990*5113495bSYour Name 
991*5113495bSYour Name 	qdf_spin_lock_bh(&spectral->detector_list_lock);
992*5113495bSYour Name 	detector_list = &spectral->detector_list[smode][ch_width];
993*5113495bSYour Name 
994*5113495bSYour Name 	for (det = 0; det < detector_list->num_detectors; det++) {
995*5113495bSYour Name 		qdf_spin_lock_bh(&spectral->session_det_map_lock);
996*5113495bSYour Name 		det_map = &spectral->det_map
997*5113495bSYour Name 				[detector_list->detectors[det]];
998*5113495bSYour Name 		dest_det_info = &det_map->dest_det_info[0];
999*5113495bSYour Name 
1000*5113495bSYour Name 		switch (det) {
1001*5113495bSYour Name 		case 0:
1002*5113495bSYour Name 			if (ch_width == CH_WIDTH_160MHZ &&
1003*5113495bSYour Name 			    is_fragmentation_160) {
1004*5113495bSYour Name 				if (rpt_info->pri20_freq <
1005*5113495bSYour Name 				    rpt_info->sscan_cfreq1)
1006*5113495bSYour Name 					cfreq = rpt_info->sscan_cfreq1 -
1007*5113495bSYour Name 						FREQ_OFFSET_40MHZ;
1008*5113495bSYour Name 				else
1009*5113495bSYour Name 					cfreq = rpt_info->sscan_cfreq1 +
1010*5113495bSYour Name 						FREQ_OFFSET_40MHZ;
1011*5113495bSYour Name 			} else
1012*5113495bSYour Name 				cfreq = rpt_info->sscan_cfreq1;
1013*5113495bSYour Name 			break;
1014*5113495bSYour Name 
1015*5113495bSYour Name 		case 1:
1016*5113495bSYour Name 			if (ch_width == CH_WIDTH_160MHZ &&
1017*5113495bSYour Name 			    is_fragmentation_160) {
1018*5113495bSYour Name 				if (rpt_info->pri20_freq <
1019*5113495bSYour Name 				    rpt_info->sscan_cfreq1)
1020*5113495bSYour Name 					cfreq = rpt_info->sscan_cfreq1 +
1021*5113495bSYour Name 						FREQ_OFFSET_40MHZ;
1022*5113495bSYour Name 				else
1023*5113495bSYour Name 					cfreq = rpt_info->sscan_cfreq1 -
1024*5113495bSYour Name 						FREQ_OFFSET_40MHZ;
1025*5113495bSYour Name 			} else
1026*5113495bSYour Name 				cfreq = rpt_info->sscan_cfreq2;
1027*5113495bSYour Name 			break;
1028*5113495bSYour Name 
1029*5113495bSYour Name 		default:
1030*5113495bSYour Name 			qdf_spin_unlock_bh(&spectral->session_det_map_lock);
1031*5113495bSYour Name 			qdf_spin_unlock_bh(&spectral->detector_list_lock);
1032*5113495bSYour Name 			qdf_spin_unlock_bh(
1033*5113495bSYour Name 					&spectral->session_report_info_lock);
1034*5113495bSYour Name 
1035*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
1036*5113495bSYour Name 		}
1037*5113495bSYour Name 
1038*5113495bSYour Name 		/* Set start and end frequencies */
1039*5113495bSYour Name 		target_if_spectral_set_start_end_freq(cfreq,
1040*5113495bSYour Name 						      ch_width,
1041*5113495bSYour Name 						      is_fragmentation_160,
1042*5113495bSYour Name 						      start_end_freq_arr);
1043*5113495bSYour Name 		dest_det_info->start_freq = start_end_freq_arr[0];
1044*5113495bSYour Name 		dest_det_info->end_freq = start_end_freq_arr[1];
1045*5113495bSYour Name 
1046*5113495bSYour Name 		qdf_spin_unlock_bh(&spectral->session_det_map_lock);
1047*5113495bSYour Name 	}
1048*5113495bSYour Name 
1049*5113495bSYour Name 	qdf_spin_unlock_bh(&spectral->detector_list_lock);
1050*5113495bSYour Name 	qdf_spin_unlock_bh(&spectral->session_report_info_lock);
1051*5113495bSYour Name 
1052*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1053*5113495bSYour Name }
1054*5113495bSYour Name 
1055*5113495bSYour Name QDF_STATUS
target_if_populate_fft_bins_info(struct target_if_spectral * spectral,enum spectral_scan_mode smode)1056*5113495bSYour Name target_if_populate_fft_bins_info(struct target_if_spectral *spectral,
1057*5113495bSYour Name 				 enum spectral_scan_mode smode)
1058*5113495bSYour Name {
1059*5113495bSYour Name 	struct per_session_det_map *det_map;
1060*5113495bSYour Name 	struct per_session_dest_det_info *dest_det_info;
1061*5113495bSYour Name 	enum phy_ch_width ch_width;
1062*5113495bSYour Name 	struct sscan_detector_list *detector_list;
1063*5113495bSYour Name 	bool is_fragmentation_160;
1064*5113495bSYour Name 	uint8_t spectral_fft_size;
1065*5113495bSYour Name 	uint8_t rpt_mode;
1066*5113495bSYour Name 	uint32_t num_fft_bins;
1067*5113495bSYour Name 	uint16_t start_bin;
1068*5113495bSYour Name 	uint8_t det;
1069*5113495bSYour Name 
1070*5113495bSYour Name 	if (!spectral) {
1071*5113495bSYour Name 		spectral_err_rl("Spectral LMAC object is null");
1072*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
1073*5113495bSYour Name 	}
1074*5113495bSYour Name 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
1075*5113495bSYour Name 		spectral_err_rl("Invalid Spectral mode");
1076*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1077*5113495bSYour Name 	}
1078*5113495bSYour Name 
1079*5113495bSYour Name 	qdf_spin_lock_bh(&spectral->session_report_info_lock);
1080*5113495bSYour Name 
1081*5113495bSYour Name 	ch_width = spectral->report_info[smode].sscan_bw;
1082*5113495bSYour Name 	is_fragmentation_160 = spectral->rparams.fragmentation_160[smode];
1083*5113495bSYour Name 	spectral_fft_size = spectral->params[smode].ss_fft_size;
1084*5113495bSYour Name 	rpt_mode = spectral->params[smode].ss_rpt_mode;
1085*5113495bSYour Name 	num_fft_bins =
1086*5113495bSYour Name 		target_if_spectral_get_num_fft_bins(spectral_fft_size,
1087*5113495bSYour Name 						    rpt_mode);
1088*5113495bSYour Name 	if (num_fft_bins < 0) {
1089*5113495bSYour Name 		qdf_spin_unlock_bh(&spectral->session_report_info_lock);
1090*5113495bSYour Name 		spectral_err_rl("Invalid number of FFT bins %d",
1091*5113495bSYour Name 				num_fft_bins);
1092*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1093*5113495bSYour Name 	}
1094*5113495bSYour Name 
1095*5113495bSYour Name 	qdf_spin_lock_bh(&spectral->detector_list_lock);
1096*5113495bSYour Name 	detector_list = &spectral->detector_list[smode][ch_width];
1097*5113495bSYour Name 
1098*5113495bSYour Name 	for (det = 0; det < detector_list->num_detectors; det++) {
1099*5113495bSYour Name 		uint16_t lb_extrabins_offset = 0;
1100*5113495bSYour Name 
1101*5113495bSYour Name 		qdf_spin_lock_bh(&spectral->session_det_map_lock);
1102*5113495bSYour Name 		det_map = &spectral->det_map
1103*5113495bSYour Name 				[detector_list->detectors[det]];
1104*5113495bSYour Name 		dest_det_info = &det_map->dest_det_info[0];
1105*5113495bSYour Name 		dest_det_info->lb_extrabins_num = spectral->lb_edge_extrabins;
1106*5113495bSYour Name 		dest_det_info->rb_extrabins_num = spectral->rb_edge_extrabins;
1107*5113495bSYour Name 		switch (det) {
1108*5113495bSYour Name 		case 0:
1109*5113495bSYour Name 			if (ch_width == CH_WIDTH_160MHZ &&
1110*5113495bSYour Name 			    is_fragmentation_160 &&
1111*5113495bSYour Name 			    spectral->report_info[smode].pri20_freq >
1112*5113495bSYour Name 			    spectral->report_info[smode].sscan_cfreq1) {
1113*5113495bSYour Name 				start_bin = num_fft_bins;
1114*5113495bSYour Name 				lb_extrabins_offset =
1115*5113495bSYour Name 					dest_det_info->lb_extrabins_num +
1116*5113495bSYour Name 					dest_det_info->rb_extrabins_num;
1117*5113495bSYour Name 			} else {
1118*5113495bSYour Name 				start_bin = 0;
1119*5113495bSYour Name 			}
1120*5113495bSYour Name 			break;
1121*5113495bSYour Name 		case 1:
1122*5113495bSYour Name 			if (ch_width == CH_WIDTH_160MHZ &&
1123*5113495bSYour Name 			    is_fragmentation_160 &&
1124*5113495bSYour Name 			    spectral->report_info[smode].pri20_freq >
1125*5113495bSYour Name 			    spectral->report_info[smode].sscan_cfreq1)
1126*5113495bSYour Name 				start_bin = 0;
1127*5113495bSYour Name 			else {
1128*5113495bSYour Name 				start_bin = num_fft_bins;
1129*5113495bSYour Name 				lb_extrabins_offset =
1130*5113495bSYour Name 					dest_det_info->lb_extrabins_num +
1131*5113495bSYour Name 					dest_det_info->rb_extrabins_num;
1132*5113495bSYour Name 			}
1133*5113495bSYour Name 			break;
1134*5113495bSYour Name 		default:
1135*5113495bSYour Name 			qdf_spin_unlock_bh(&spectral->session_det_map_lock);
1136*5113495bSYour Name 			qdf_spin_unlock_bh(&spectral->detector_list_lock);
1137*5113495bSYour Name 			qdf_spin_unlock_bh(
1138*5113495bSYour Name 					&spectral->session_report_info_lock);
1139*5113495bSYour Name 
1140*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
1141*5113495bSYour Name 		}
1142*5113495bSYour Name 		dest_det_info->dest_start_bin_idx = start_bin;
1143*5113495bSYour Name 		dest_det_info->dest_end_bin_idx =
1144*5113495bSYour Name 					dest_det_info->dest_start_bin_idx;
1145*5113495bSYour Name 		if (num_fft_bins > 0)
1146*5113495bSYour Name 			dest_det_info->dest_end_bin_idx += (num_fft_bins - 1);
1147*5113495bSYour Name 
1148*5113495bSYour Name 		if (dest_det_info->lb_extrabins_num) {
1149*5113495bSYour Name 			if (is_ch_width_160_or_80p80(ch_width)) {
1150*5113495bSYour Name 				dest_det_info->lb_extrabins_start_idx =
1151*5113495bSYour Name 							2 * num_fft_bins +
1152*5113495bSYour Name 							lb_extrabins_offset;
1153*5113495bSYour Name 			} else {
1154*5113495bSYour Name 				dest_det_info->lb_extrabins_start_idx =
1155*5113495bSYour Name 								num_fft_bins;
1156*5113495bSYour Name 			}
1157*5113495bSYour Name 		}
1158*5113495bSYour Name 		if (dest_det_info->rb_extrabins_num)
1159*5113495bSYour Name 			dest_det_info->rb_extrabins_start_idx =
1160*5113495bSYour Name 					dest_det_info->lb_extrabins_start_idx +
1161*5113495bSYour Name 					dest_det_info->lb_extrabins_num;
1162*5113495bSYour Name 		dest_det_info->src_start_bin_idx = 0;
1163*5113495bSYour Name 		qdf_spin_unlock_bh(&spectral->session_det_map_lock);
1164*5113495bSYour Name 	}
1165*5113495bSYour Name 	qdf_spin_unlock_bh(&spectral->detector_list_lock);
1166*5113495bSYour Name 	qdf_spin_unlock_bh(&spectral->session_report_info_lock);
1167*5113495bSYour Name 
1168*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1169*5113495bSYour Name }
1170*5113495bSYour Name 
1171*5113495bSYour Name /**
1172*5113495bSYour Name  * target_if_update_session_info_from_report_ctx() - Update per-session
1173*5113495bSYour Name  * information from the consume report context. This includes populating start
1174*5113495bSYour Name  * and end bin indices, and set the start and end frequency per-detector.
1175*5113495bSYour Name  * @spectral: Pointer to target_if spectral internal structure
1176*5113495bSYour Name  * @fft_bin_size: Size of 1 FFT bin (in bytes)
1177*5113495bSYour Name  * @cfreq1: Center frequency of Detector 1
1178*5113495bSYour Name  * @cfreq2: Center frequency of Detector 2
1179*5113495bSYour Name  * @smode: Spectral scan mode
1180*5113495bSYour Name  *
1181*5113495bSYour Name  * Update per-session information from the consume report context.
1182*5113495bSYour Name  *
1183*5113495bSYour Name  * Return: Success/Failure
1184*5113495bSYour Name  */
1185*5113495bSYour Name static QDF_STATUS
target_if_update_session_info_from_report_ctx(struct target_if_spectral * spectral,uint8_t fft_bin_size,uint32_t cfreq1,uint32_t cfreq2,enum spectral_scan_mode smode)1186*5113495bSYour Name target_if_update_session_info_from_report_ctx(
1187*5113495bSYour Name 				struct target_if_spectral *spectral,
1188*5113495bSYour Name 				uint8_t fft_bin_size,
1189*5113495bSYour Name 				uint32_t cfreq1, uint32_t cfreq2,
1190*5113495bSYour Name 				enum spectral_scan_mode smode)
1191*5113495bSYour Name {
1192*5113495bSYour Name 	struct target_if_spectral_ops *p_sops;
1193*5113495bSYour Name 	struct per_session_report_info *rpt_info;
1194*5113495bSYour Name 	struct per_session_det_map *det_map;
1195*5113495bSYour Name 	struct per_session_dest_det_info *dest_det_info;
1196*5113495bSYour Name 	enum phy_ch_width ch_width;
1197*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
1198*5113495bSYour Name 	bool is_fragmentation_160;
1199*5113495bSYour Name 	uint32_t start_end_freq_arr[2];
1200*5113495bSYour Name 	QDF_STATUS ret;
1201*5113495bSYour Name 	bool is_session_info_expected;
1202*5113495bSYour Name 
1203*5113495bSYour Name 	if (!spectral) {
1204*5113495bSYour Name 		spectral_err_rl("Spectral LMAC object is null");
1205*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
1206*5113495bSYour Name 	}
1207*5113495bSYour Name 
1208*5113495bSYour Name 	ret = spectral_is_session_info_expected_from_target(
1209*5113495bSYour Name 				spectral->pdev_obj,
1210*5113495bSYour Name 				&is_session_info_expected);
1211*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(ret)) {
1212*5113495bSYour Name 		spectral_err_rl("Failed to check if session info is expected");
1213*5113495bSYour Name 		return ret;
1214*5113495bSYour Name 	}
1215*5113495bSYour Name 
1216*5113495bSYour Name 	/* If FW sends this information, use it, no need to get it from here */
1217*5113495bSYour Name 	if (is_session_info_expected)
1218*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
1219*5113495bSYour Name 
1220*5113495bSYour Name 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
1221*5113495bSYour Name 		spectral_err_rl("Invalid Spectral mode");
1222*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1223*5113495bSYour Name 	}
1224*5113495bSYour Name 	if (!spectral->pdev_obj) {
1225*5113495bSYour Name 		spectral_err_rl("Spectral PDEV is null");
1226*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
1227*5113495bSYour Name 	}
1228*5113495bSYour Name 
1229*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(spectral->pdev_obj);
1230*5113495bSYour Name 	if (!psoc) {
1231*5113495bSYour Name 		spectral_err_rl("psoc is null");
1232*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
1233*5113495bSYour Name 	}
1234*5113495bSYour Name 
1235*5113495bSYour Name 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
1236*5113495bSYour Name 
1237*5113495bSYour Name 	qdf_spin_lock_bh(&spectral->session_report_info_lock);
1238*5113495bSYour Name 
1239*5113495bSYour Name 	rpt_info = &spectral->report_info[smode];
1240*5113495bSYour Name 	ch_width = rpt_info->sscan_bw;
1241*5113495bSYour Name 	is_fragmentation_160 = spectral->rparams.fragmentation_160[smode];
1242*5113495bSYour Name 
1243*5113495bSYour Name 	rpt_info->pri20_freq = p_sops->get_current_channel(spectral, smode);
1244*5113495bSYour Name 	rpt_info->cfreq1 = cfreq1;
1245*5113495bSYour Name 	rpt_info->cfreq2 = cfreq2;
1246*5113495bSYour Name 
1247*5113495bSYour Name 	if (spectral_debug_level & DEBUG_SPECTRAL4)
1248*5113495bSYour Name 		spectral_debug("Before conversion: cfreq1: %u cfreq2: %u",
1249*5113495bSYour Name 			       rpt_info->cfreq1, rpt_info->cfreq2);
1250*5113495bSYour Name 
1251*5113495bSYour Name 	ret = target_if_spectral_unify_cfreq_format(
1252*5113495bSYour Name 		spectral, &rpt_info->cfreq1, &rpt_info->cfreq2,
1253*5113495bSYour Name 		rpt_info->pri20_freq, rpt_info->operating_bw, smode);
1254*5113495bSYour Name 
1255*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(ret)) {
1256*5113495bSYour Name 		qdf_spin_unlock_bh(&spectral->session_report_info_lock);
1257*5113495bSYour Name 		spectral_err_rl("Unable to unify cfreq1/cfreq2");
1258*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1259*5113495bSYour Name 	}
1260*5113495bSYour Name 
1261*5113495bSYour Name 	if (spectral_debug_level & DEBUG_SPECTRAL4)
1262*5113495bSYour Name 		spectral_debug("After conversion: cfreq1: %d cfreq2: %d",
1263*5113495bSYour Name 			       rpt_info->cfreq1, rpt_info->cfreq2);
1264*5113495bSYour Name 
1265*5113495bSYour Name 	/* For Agile mode, sscan_cfreq1 and sscan_cfreq2 are populated
1266*5113495bSYour Name 	 * during Spectral start scan
1267*5113495bSYour Name 	 */
1268*5113495bSYour Name 	if (smode == SPECTRAL_SCAN_MODE_NORMAL) {
1269*5113495bSYour Name 		rpt_info->sscan_cfreq1 = rpt_info->cfreq1;
1270*5113495bSYour Name 		rpt_info->sscan_cfreq2 = rpt_info->cfreq2;
1271*5113495bSYour Name 	}
1272*5113495bSYour Name 	qdf_spin_unlock_bh(&spectral->session_report_info_lock);
1273*5113495bSYour Name 
1274*5113495bSYour Name 	if (ch_width == CH_WIDTH_80P80MHZ && wlan_psoc_nif_fw_ext_cap_get(
1275*5113495bSYour Name 	    psoc, WLAN_SOC_RESTRICTED_80P80_SUPPORT)) {
1276*5113495bSYour Name 		/* Restricted 80p80 */
1277*5113495bSYour Name 		struct spectral_fft_bin_markers_160_165mhz *marker;
1278*5113495bSYour Name 		struct sscan_detector_list *detector_list;
1279*5113495bSYour Name 
1280*5113495bSYour Name 		marker = &spectral->rparams.marker[smode];
1281*5113495bSYour Name 		if (!marker->is_valid)
1282*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
1283*5113495bSYour Name 
1284*5113495bSYour Name 		/**
1285*5113495bSYour Name 		 * Restricted 80p80 on Pine has only 1 detector for
1286*5113495bSYour Name 		 * normal/agile spectral scan. So, detector_list will
1287*5113495bSYour Name 		 * have only one detector
1288*5113495bSYour Name 		 */
1289*5113495bSYour Name 		qdf_spin_lock_bh(&spectral->detector_list_lock);
1290*5113495bSYour Name 		detector_list = &spectral->detector_list[smode][ch_width];
1291*5113495bSYour Name 
1292*5113495bSYour Name 		qdf_spin_lock_bh(&spectral->session_det_map_lock);
1293*5113495bSYour Name 		det_map = &spectral->det_map[detector_list->detectors[0]];
1294*5113495bSYour Name 
1295*5113495bSYour Name 		dest_det_info = &det_map->dest_det_info[0];
1296*5113495bSYour Name 		dest_det_info->dest_start_bin_idx = marker->start_pri80;
1297*5113495bSYour Name 		dest_det_info->dest_end_bin_idx =
1298*5113495bSYour Name 					dest_det_info->dest_start_bin_idx +
1299*5113495bSYour Name 					marker->num_pri80 - 1;
1300*5113495bSYour Name 		dest_det_info->src_start_bin_idx = marker->start_pri80 *
1301*5113495bSYour Name 						   fft_bin_size;
1302*5113495bSYour Name 		/* Set start and end frequencies */
1303*5113495bSYour Name 		qdf_spin_lock_bh(&spectral->session_report_info_lock);
1304*5113495bSYour Name 		target_if_spectral_set_start_end_freq(rpt_info->sscan_cfreq1,
1305*5113495bSYour Name 						      ch_width,
1306*5113495bSYour Name 						      is_fragmentation_160,
1307*5113495bSYour Name 						      start_end_freq_arr);
1308*5113495bSYour Name 		dest_det_info->start_freq = start_end_freq_arr[0];
1309*5113495bSYour Name 		dest_det_info->end_freq = start_end_freq_arr[1];
1310*5113495bSYour Name 
1311*5113495bSYour Name 
1312*5113495bSYour Name 		dest_det_info = &det_map->dest_det_info[1];
1313*5113495bSYour Name 		dest_det_info->dest_start_bin_idx = marker->start_sec80;
1314*5113495bSYour Name 		dest_det_info->dest_end_bin_idx =
1315*5113495bSYour Name 					dest_det_info->dest_start_bin_idx +
1316*5113495bSYour Name 					marker->num_sec80 - 1;
1317*5113495bSYour Name 		dest_det_info->src_start_bin_idx = marker->start_sec80 *
1318*5113495bSYour Name 						   fft_bin_size;
1319*5113495bSYour Name 		/* Set start and end frequencies */
1320*5113495bSYour Name 		target_if_spectral_set_start_end_freq(rpt_info->sscan_cfreq2,
1321*5113495bSYour Name 						      ch_width,
1322*5113495bSYour Name 						      is_fragmentation_160,
1323*5113495bSYour Name 						      start_end_freq_arr);
1324*5113495bSYour Name 		dest_det_info->start_freq = start_end_freq_arr[0];
1325*5113495bSYour Name 		dest_det_info->end_freq = start_end_freq_arr[1];
1326*5113495bSYour Name 
1327*5113495bSYour Name 		dest_det_info = &det_map->dest_det_info[2];
1328*5113495bSYour Name 		dest_det_info->dest_start_bin_idx = marker->start_5mhz;
1329*5113495bSYour Name 		dest_det_info->dest_end_bin_idx =
1330*5113495bSYour Name 					dest_det_info->dest_start_bin_idx +
1331*5113495bSYour Name 					marker->num_5mhz - 1;
1332*5113495bSYour Name 		dest_det_info->src_start_bin_idx = marker->start_5mhz *
1333*5113495bSYour Name 						   fft_bin_size;
1334*5113495bSYour Name 		/* Set start and end frequencies */
1335*5113495bSYour Name 		dest_det_info->start_freq =
1336*5113495bSYour Name 				min(det_map->dest_det_info[0].end_freq,
1337*5113495bSYour Name 				    det_map->dest_det_info[1].end_freq);
1338*5113495bSYour Name 		dest_det_info->end_freq =
1339*5113495bSYour Name 				max(det_map->dest_det_info[0].start_freq,
1340*5113495bSYour Name 				    det_map->dest_det_info[1].start_freq);
1341*5113495bSYour Name 
1342*5113495bSYour Name 		qdf_spin_unlock_bh(&spectral->session_report_info_lock);
1343*5113495bSYour Name 		qdf_spin_unlock_bh(&spectral->session_det_map_lock);
1344*5113495bSYour Name 		qdf_spin_unlock_bh(&spectral->detector_list_lock);
1345*5113495bSYour Name 	} else {
1346*5113495bSYour Name 		ret = target_if_populate_fft_bins_info(spectral, smode);
1347*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(ret)) {
1348*5113495bSYour Name 			spectral_err_rl("Error in populating fft bins info");
1349*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
1350*5113495bSYour Name 		}
1351*5113495bSYour Name 
1352*5113495bSYour Name 		ret = target_if_populate_det_start_end_freqs(spectral, smode);
1353*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(ret)) {
1354*5113495bSYour Name 			spectral_err_rl("Failed to populate start/end freqs");
1355*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
1356*5113495bSYour Name 		}
1357*5113495bSYour Name 	}
1358*5113495bSYour Name 
1359*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1360*5113495bSYour Name }
1361*5113495bSYour Name #endif /* OPTIMIZED_SAMP_MESSAGE */
1362*5113495bSYour Name 
1363*5113495bSYour Name #ifdef OPTIMIZED_SAMP_MESSAGE
1364*5113495bSYour Name /**
1365*5113495bSYour Name  * target_if_spectral_populate_samp_params_gen2() - Populate the SAMP params
1366*5113495bSYour Name  * for gen2. SAMP params are to be used for populating SAMP msg.
1367*5113495bSYour Name  * @spectral: Pointer to spectral object
1368*5113495bSYour Name  * @phyerr_info: Pointer to processed phyerr info
1369*5113495bSYour Name  * @params: Pointer to Spectral SAMP message fields to be populated
1370*5113495bSYour Name  *
1371*5113495bSYour Name  * Populate the SAMP params for gen2, which will be used to populate SAMP msg.
1372*5113495bSYour Name  *
1373*5113495bSYour Name  * Return: Success/Failure
1374*5113495bSYour Name  */
1375*5113495bSYour Name static QDF_STATUS
target_if_spectral_populate_samp_params_gen2(struct target_if_spectral * spectral,struct spectral_process_phyerr_info_gen2 * phyerr_info,struct target_if_samp_msg_params * params)1376*5113495bSYour Name target_if_spectral_populate_samp_params_gen2(
1377*5113495bSYour Name 			struct target_if_spectral *spectral,
1378*5113495bSYour Name 			struct spectral_process_phyerr_info_gen2 *phyerr_info,
1379*5113495bSYour Name 			struct target_if_samp_msg_params *params)
1380*5113495bSYour Name {
1381*5113495bSYour Name 	uint8_t chn_idx_highest_enabled;
1382*5113495bSYour Name 	uint8_t chn_idx_lowest_enabled;
1383*5113495bSYour Name 	int8_t control_rssi;
1384*5113495bSYour Name 	int8_t extension_rssi;
1385*5113495bSYour Name 	struct target_if_spectral_rfqual_info *p_rfqual;
1386*5113495bSYour Name 	struct spectral_search_fft_info_gen2 *p_sfft;
1387*5113495bSYour Name 	struct spectral_phyerr_fft_gen2 *pfft;
1388*5113495bSYour Name 	struct target_if_spectral_acs_stats *acs_stats;
1389*5113495bSYour Name 	enum phy_ch_width ch_width;
1390*5113495bSYour Name 	enum spectral_scan_mode smode = SPECTRAL_SCAN_MODE_NORMAL;
1391*5113495bSYour Name 
1392*5113495bSYour Name 	if (!spectral) {
1393*5113495bSYour Name 		spectral_err_rl("Spectral LMAC object is null");
1394*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
1395*5113495bSYour Name 	}
1396*5113495bSYour Name 	if (!phyerr_info) {
1397*5113495bSYour Name 		spectral_err_rl("Pointer to phyerr info is null");
1398*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
1399*5113495bSYour Name 	}
1400*5113495bSYour Name 	if (!params) {
1401*5113495bSYour Name 		spectral_err_rl("SAMP msg params structure is null");
1402*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
1403*5113495bSYour Name 	}
1404*5113495bSYour Name 
1405*5113495bSYour Name 	qdf_spin_lock_bh(&spectral->session_report_info_lock);
1406*5113495bSYour Name 	ch_width = spectral->report_info[smode].sscan_bw;
1407*5113495bSYour Name 	qdf_spin_unlock_bh(&spectral->session_report_info_lock);
1408*5113495bSYour Name 
1409*5113495bSYour Name 	acs_stats = phyerr_info->acs_stats;
1410*5113495bSYour Name 	pfft = phyerr_info->pfft;
1411*5113495bSYour Name 	p_sfft = phyerr_info->p_sfft;
1412*5113495bSYour Name 	p_rfqual = phyerr_info->p_rfqual;
1413*5113495bSYour Name 
1414*5113495bSYour Name 	params->hw_detector_id = phyerr_info->seg_id;
1415*5113495bSYour Name 	params->rssi = p_rfqual->rssi_comb;
1416*5113495bSYour Name 	if (spectral->is_sec80_rssi_war_required && phyerr_info->seg_id == 1)
1417*5113495bSYour Name 		params->rssi = target_if_get_combrssi_sec80_seg_gen2(spectral,
1418*5113495bSYour Name 								     p_sfft);
1419*5113495bSYour Name 
1420*5113495bSYour Name 	chn_idx_highest_enabled =
1421*5113495bSYour Name 		   ((spectral->params[smode].ss_chn_mask & 0x8) ? 3 :
1422*5113495bSYour Name 		    (spectral->params[smode].ss_chn_mask & 0x4) ? 2 :
1423*5113495bSYour Name 		    (spectral->params[smode].ss_chn_mask & 0x2) ? 1 : 0);
1424*5113495bSYour Name 	chn_idx_lowest_enabled =
1425*5113495bSYour Name 		   ((spectral->params[smode].ss_chn_mask & 0x1) ? 0 :
1426*5113495bSYour Name 		    (spectral->params[smode].ss_chn_mask & 0x2) ? 1 :
1427*5113495bSYour Name 		    (spectral->params[smode].ss_chn_mask & 0x4) ? 2 : 3);
1428*5113495bSYour Name 	control_rssi =
1429*5113495bSYour Name 		p_rfqual->pc_rssi_info[chn_idx_highest_enabled].rssi_pri20;
1430*5113495bSYour Name 	extension_rssi =
1431*5113495bSYour Name 		p_rfqual->pc_rssi_info[chn_idx_highest_enabled].rssi_sec20;
1432*5113495bSYour Name 
1433*5113495bSYour Name 	if (spectral->upper_is_control)
1434*5113495bSYour Name 		params->upper_rssi = control_rssi;
1435*5113495bSYour Name 	else
1436*5113495bSYour Name 		params->upper_rssi = extension_rssi;
1437*5113495bSYour Name 
1438*5113495bSYour Name 	if (spectral->lower_is_control)
1439*5113495bSYour Name 		params->lower_rssi = control_rssi;
1440*5113495bSYour Name 	else
1441*5113495bSYour Name 		params->lower_rssi = extension_rssi;
1442*5113495bSYour Name 
1443*5113495bSYour Name 	if (spectral->sc_spectral_noise_pwr_cal) {
1444*5113495bSYour Name 		int idx;
1445*5113495bSYour Name 
1446*5113495bSYour Name 		for (idx = 0; idx < HOST_MAX_ANTENNA; idx++) {
1447*5113495bSYour Name 			params->chain_ctl_rssi[idx] =
1448*5113495bSYour Name 				p_rfqual->pc_rssi_info[idx].rssi_pri20;
1449*5113495bSYour Name 			params->chain_ext_rssi[idx] =
1450*5113495bSYour Name 				p_rfqual->pc_rssi_info[idx].rssi_sec20;
1451*5113495bSYour Name 		}
1452*5113495bSYour Name 	}
1453*5113495bSYour Name 	params->timestamp = (phyerr_info->tsf64 & SPECTRAL_TSMASK);
1454*5113495bSYour Name 	params->max_mag = p_sfft->peak_mag;
1455*5113495bSYour Name 	params->max_index = p_sfft->peak_inx;
1456*5113495bSYour Name 
1457*5113495bSYour Name 	/*
1458*5113495bSYour Name 	 * For VHT80_80/VHT160, the noise floor for primary
1459*5113495bSYour Name 	 * 80MHz segment is populated with the lowest enabled
1460*5113495bSYour Name 	 * antenna chain and the noise floor for secondary 80MHz segment
1461*5113495bSYour Name 	 * is populated with the highest enabled antenna chain.
1462*5113495bSYour Name 	 * For modes upto VHT80, the noise floor is populated with the
1463*5113495bSYour Name 	 * one corresponding to the highest enabled antenna chain.
1464*5113495bSYour Name 	 */
1465*5113495bSYour Name 	if (is_ch_width_160_or_80p80(ch_width) && phyerr_info->seg_id == 0)
1466*5113495bSYour Name 		params->noise_floor =
1467*5113495bSYour Name 				p_rfqual->noise_floor[chn_idx_lowest_enabled];
1468*5113495bSYour Name 	else
1469*5113495bSYour Name 		params->noise_floor =
1470*5113495bSYour Name 				p_rfqual->noise_floor[chn_idx_highest_enabled];
1471*5113495bSYour Name 
1472*5113495bSYour Name 	acs_stats->ctrl_nf = params->noise_floor;
1473*5113495bSYour Name 	acs_stats->ext_nf = params->noise_floor;
1474*5113495bSYour Name 	acs_stats->nfc_ctl_rssi = control_rssi;
1475*5113495bSYour Name 	acs_stats->nfc_ext_rssi = extension_rssi;
1476*5113495bSYour Name 
1477*5113495bSYour Name 	params->bin_pwr_data = (uint8_t *)pfft;
1478*5113495bSYour Name 
1479*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1480*5113495bSYour Name }
1481*5113495bSYour Name 
1482*5113495bSYour Name int
target_if_process_phyerr_gen2(struct target_if_spectral * spectral,uint8_t * data,uint32_t datalen,struct target_if_spectral_rfqual_info * p_rfqual,struct target_if_spectral_chan_info * p_chaninfo,uint64_t tsf64,struct target_if_spectral_acs_stats * acs_stats)1483*5113495bSYour Name target_if_process_phyerr_gen2(struct target_if_spectral *spectral,
1484*5113495bSYour Name 			      uint8_t *data,
1485*5113495bSYour Name 			      uint32_t datalen,
1486*5113495bSYour Name 			      struct target_if_spectral_rfqual_info *p_rfqual,
1487*5113495bSYour Name 			      struct target_if_spectral_chan_info *p_chaninfo,
1488*5113495bSYour Name 			      uint64_t tsf64,
1489*5113495bSYour Name 			      struct target_if_spectral_acs_stats *acs_stats)
1490*5113495bSYour Name {
1491*5113495bSYour Name 	/*
1492*5113495bSYour Name 	 * XXX : The classifier do not use all the members of the SAMP
1493*5113495bSYour Name 	 *       message data format.
1494*5113495bSYour Name 	 *       The classifier only depends upon the following parameters
1495*5113495bSYour Name 	 *
1496*5113495bSYour Name 	 *          1. Frequency
1497*5113495bSYour Name 	 *          2. Spectral RSSI
1498*5113495bSYour Name 	 *          3. Bin Power Count
1499*5113495bSYour Name 	 *          4. Bin Power values
1500*5113495bSYour Name 	 *          5. Spectral Timestamp
1501*5113495bSYour Name 	 *          6. MAC Address
1502*5113495bSYour Name 	 *
1503*5113495bSYour Name 	 *       This function prepares the params structure and populates it
1504*5113495bSYour Name 	 *       with relevant values, this is in turn passed to
1505*5113495bSYour Name 	 *       spectral_fill_samp_msg()
1506*5113495bSYour Name 	 *       to prepare fully formatted Spectral SAMP message
1507*5113495bSYour Name 	 *
1508*5113495bSYour Name 	 *       XXX : Need to verify
1509*5113495bSYour Name 	 *          1. Order of FFT bin values
1510*5113495bSYour Name 	 *
1511*5113495bSYour Name 	 */
1512*5113495bSYour Name 
1513*5113495bSYour Name 	struct target_if_samp_msg_params params;
1514*5113495bSYour Name 	struct spectral_search_fft_info_gen2 search_fft_info;
1515*5113495bSYour Name 	struct spectral_search_fft_info_gen2 *p_sfft = &search_fft_info;
1516*5113495bSYour Name 	struct spectral_search_fft_info_gen2 search_fft_info_sec80;
1517*5113495bSYour Name 	struct spectral_search_fft_info_gen2 *p_sfft_sec80 =
1518*5113495bSYour Name 		&search_fft_info_sec80;
1519*5113495bSYour Name 	uint32_t segid_skiplen = 0;
1520*5113495bSYour Name 	struct spectral_phyerr_tlv_gen2 *ptlv = NULL;
1521*5113495bSYour Name 	struct spectral_phyerr_tlv_gen2 *ptlv_sec80 = NULL;
1522*5113495bSYour Name 	struct spectral_phyerr_fft_gen2 *pfft = NULL;
1523*5113495bSYour Name 	struct spectral_phyerr_fft_gen2 *pfft_sec80 = NULL;
1524*5113495bSYour Name 	struct spectral_process_phyerr_info_gen2 process_phyerr_fields;
1525*5113495bSYour Name 	struct spectral_process_phyerr_info_gen2 *phyerr_info =
1526*5113495bSYour Name 						&process_phyerr_fields;
1527*5113495bSYour Name 	uint8_t segid = 0;
1528*5113495bSYour Name 	uint8_t segid_sec80;
1529*5113495bSYour Name 	enum phy_ch_width ch_width;
1530*5113495bSYour Name 	QDF_STATUS ret;
1531*5113495bSYour Name 	struct target_if_spectral_ops *p_sops;
1532*5113495bSYour Name 
1533*5113495bSYour Name 	if (!spectral) {
1534*5113495bSYour Name 		spectral_err_rl("Spectral LMAC object is null");
1535*5113495bSYour Name 		return -EPERM;
1536*5113495bSYour Name 	}
1537*5113495bSYour Name 
1538*5113495bSYour Name 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
1539*5113495bSYour Name 	/* Drop the sample if Spectral is not active */
1540*5113495bSYour Name 	if (!p_sops->is_spectral_active(spectral,
1541*5113495bSYour Name 					SPECTRAL_SCAN_MODE_NORMAL)) {
1542*5113495bSYour Name 		spectral_info_rl("Spectral scan is not active");
1543*5113495bSYour Name 		goto fail_no_print;
1544*5113495bSYour Name 	}
1545*5113495bSYour Name 
1546*5113495bSYour Name 	if (!data) {
1547*5113495bSYour Name 		spectral_err_rl("Phyerror event buffer is null");
1548*5113495bSYour Name 		goto fail;
1549*5113495bSYour Name 	}
1550*5113495bSYour Name 	if (!p_rfqual) {
1551*5113495bSYour Name 		spectral_err_rl("RF quality information is null");
1552*5113495bSYour Name 		goto fail;
1553*5113495bSYour Name 	}
1554*5113495bSYour Name 	if (!p_chaninfo) {
1555*5113495bSYour Name 		spectral_err_rl("Channel information is null");
1556*5113495bSYour Name 		goto fail;
1557*5113495bSYour Name 	}
1558*5113495bSYour Name 	if (!acs_stats) {
1559*5113495bSYour Name 		spectral_err_rl("ACS stats pointer is null");
1560*5113495bSYour Name 		goto fail;
1561*5113495bSYour Name 	}
1562*5113495bSYour Name 
1563*5113495bSYour Name 	qdf_spin_lock_bh(&spectral->session_report_info_lock);
1564*5113495bSYour Name 	ch_width = spectral->report_info[SPECTRAL_SCAN_MODE_NORMAL].sscan_bw;
1565*5113495bSYour Name 	qdf_spin_unlock_bh(&spectral->session_report_info_lock);
1566*5113495bSYour Name 
1567*5113495bSYour Name 	ptlv = (struct spectral_phyerr_tlv_gen2 *)data;
1568*5113495bSYour Name 
1569*5113495bSYour Name 	if (spectral->is_160_format)
1570*5113495bSYour Name 		segid_skiplen = sizeof(SPECTRAL_SEGID_INFO);
1571*5113495bSYour Name 
1572*5113495bSYour Name 	pfft = (struct spectral_phyerr_fft_gen2 *)(
1573*5113495bSYour Name 			data +
1574*5113495bSYour Name 			sizeof(struct spectral_phyerr_tlv_gen2) +
1575*5113495bSYour Name 			sizeof(struct spectral_phyerr_hdr_gen2) +
1576*5113495bSYour Name 			segid_skiplen);
1577*5113495bSYour Name 
1578*5113495bSYour Name 	/*
1579*5113495bSYour Name 	 * XXX Extend SPECTRAL_DPRINTK() to use spectral_debug_level,
1580*5113495bSYour Name 	 * and use this facility inside spectral_dump_phyerr_data()
1581*5113495bSYour Name 	 * and supporting functions.
1582*5113495bSYour Name 	 */
1583*5113495bSYour Name 	if (spectral_debug_level & (DEBUG_SPECTRAL2 | DEBUG_SPECTRAL4))
1584*5113495bSYour Name 		target_if_spectral_dump_phyerr_data_gen2(
1585*5113495bSYour Name 					data, datalen,
1586*5113495bSYour Name 					spectral->is_160_format);
1587*5113495bSYour Name 
1588*5113495bSYour Name 	if (ptlv->signature != SPECTRAL_PHYERR_SIGNATURE_GEN2) {
1589*5113495bSYour Name 		/*
1590*5113495bSYour Name 		 * EV# 118023: We tentatively disable the below print
1591*5113495bSYour Name 		 * and provide stats instead.
1592*5113495bSYour Name 		 */
1593*5113495bSYour Name 		spectral->diag_stats.spectral_mismatch++;
1594*5113495bSYour Name 		goto fail;
1595*5113495bSYour Name 	}
1596*5113495bSYour Name 
1597*5113495bSYour Name 	qdf_mem_zero(&params, sizeof(params));
1598*5113495bSYour Name 
1599*5113495bSYour Name 	if (ptlv->tag == TLV_TAG_SEARCH_FFT_REPORT_GEN2) {
1600*5113495bSYour Name 		if (spectral->is_160_format) {
1601*5113495bSYour Name 			segid = *((SPECTRAL_SEGID_INFO *)(
1602*5113495bSYour Name 				  (uint8_t *)ptlv +
1603*5113495bSYour Name 				  sizeof(struct spectral_phyerr_tlv_gen2) +
1604*5113495bSYour Name 				  sizeof(struct spectral_phyerr_hdr_gen2)));
1605*5113495bSYour Name 
1606*5113495bSYour Name 			if (segid != 0) {
1607*5113495bSYour Name 				struct spectral_diag_stats *p_diag_stats =
1608*5113495bSYour Name 					&spectral->diag_stats;
1609*5113495bSYour Name 				p_diag_stats->spectral_vhtseg1id_mismatch++;
1610*5113495bSYour Name 				goto fail;
1611*5113495bSYour Name 			}
1612*5113495bSYour Name 		}
1613*5113495bSYour Name 
1614*5113495bSYour Name 		target_if_process_sfft_report_gen2(ptlv, ptlv->length,
1615*5113495bSYour Name 						   p_sfft);
1616*5113495bSYour Name 
1617*5113495bSYour Name 		ret = target_if_update_session_info_from_report_ctx(
1618*5113495bSYour Name 						spectral, FFT_BIN_SIZE_1BYTE,
1619*5113495bSYour Name 						p_chaninfo->center_freq1,
1620*5113495bSYour Name 						p_chaninfo->center_freq2,
1621*5113495bSYour Name 						SPECTRAL_SCAN_MODE_NORMAL);
1622*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(ret)) {
1623*5113495bSYour Name 			spectral_err_rl("Failed to update per-session info");
1624*5113495bSYour Name 			goto fail;
1625*5113495bSYour Name 		}
1626*5113495bSYour Name 
1627*5113495bSYour Name 		phyerr_info->p_rfqual = p_rfqual;
1628*5113495bSYour Name 		phyerr_info->p_sfft = p_sfft;
1629*5113495bSYour Name 		phyerr_info->pfft = pfft;
1630*5113495bSYour Name 		phyerr_info->acs_stats = acs_stats;
1631*5113495bSYour Name 		phyerr_info->tsf64 = tsf64;
1632*5113495bSYour Name 		phyerr_info->seg_id = segid;
1633*5113495bSYour Name 
1634*5113495bSYour Name 		ret = target_if_spectral_populate_samp_params_gen2(spectral,
1635*5113495bSYour Name 								   phyerr_info,
1636*5113495bSYour Name 								   &params);
1637*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(ret)) {
1638*5113495bSYour Name 			spectral_err_rl("Failed to populate SAMP params");
1639*5113495bSYour Name 			goto fail;
1640*5113495bSYour Name 		}
1641*5113495bSYour Name 
1642*5113495bSYour Name 		ret = target_if_spectral_fill_samp_msg(spectral, &params);
1643*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(ret)) {
1644*5113495bSYour Name 			spectral_err_rl("Failed to fill the SAMP msg");
1645*5113495bSYour Name 			goto fail;
1646*5113495bSYour Name 		}
1647*5113495bSYour Name 
1648*5113495bSYour Name 		if (spectral->is_160_format &&
1649*5113495bSYour Name 		    is_ch_width_160_or_80p80(ch_width)) {
1650*5113495bSYour Name 			/*
1651*5113495bSYour Name 			 * We expect to see one more Search FFT report, and it
1652*5113495bSYour Name 			 * should be equal in size to the current one.
1653*5113495bSYour Name 			 */
1654*5113495bSYour Name 			if (datalen < (
1655*5113495bSYour Name 				2 * (sizeof(struct spectral_phyerr_tlv_gen2) +
1656*5113495bSYour Name 				     ptlv->length))) {
1657*5113495bSYour Name 				struct spectral_diag_stats *p_diag_stats =
1658*5113495bSYour Name 					&spectral->diag_stats;
1659*5113495bSYour Name 				p_diag_stats->spectral_sec80_sfft_insufflen++;
1660*5113495bSYour Name 				goto fail;
1661*5113495bSYour Name 			}
1662*5113495bSYour Name 
1663*5113495bSYour Name 			ptlv_sec80 = (struct spectral_phyerr_tlv_gen2 *)(
1664*5113495bSYour Name 				      data +
1665*5113495bSYour Name 				      sizeof(struct spectral_phyerr_tlv_gen2) +
1666*5113495bSYour Name 				      ptlv->length);
1667*5113495bSYour Name 
1668*5113495bSYour Name 			if (ptlv_sec80->signature !=
1669*5113495bSYour Name 			    SPECTRAL_PHYERR_SIGNATURE_GEN2) {
1670*5113495bSYour Name 				spectral->diag_stats.spectral_mismatch++;
1671*5113495bSYour Name 				goto fail;
1672*5113495bSYour Name 			}
1673*5113495bSYour Name 
1674*5113495bSYour Name 			if (ptlv_sec80->tag != TLV_TAG_SEARCH_FFT_REPORT_GEN2) {
1675*5113495bSYour Name 				spectral->diag_stats.spectral_no_sec80_sfft++;
1676*5113495bSYour Name 				goto fail;
1677*5113495bSYour Name 			}
1678*5113495bSYour Name 
1679*5113495bSYour Name 			segid_sec80 = *((SPECTRAL_SEGID_INFO *)(
1680*5113495bSYour Name 				(uint8_t *)ptlv_sec80 +
1681*5113495bSYour Name 				sizeof(struct spectral_phyerr_tlv_gen2) +
1682*5113495bSYour Name 				sizeof(struct spectral_phyerr_hdr_gen2)));
1683*5113495bSYour Name 
1684*5113495bSYour Name 			if (segid_sec80 != 1) {
1685*5113495bSYour Name 				struct spectral_diag_stats *p_diag_stats =
1686*5113495bSYour Name 					&spectral->diag_stats;
1687*5113495bSYour Name 				p_diag_stats->spectral_vhtseg2id_mismatch++;
1688*5113495bSYour Name 				goto fail;
1689*5113495bSYour Name 			}
1690*5113495bSYour Name 
1691*5113495bSYour Name 			target_if_process_sfft_report_gen2(ptlv_sec80,
1692*5113495bSYour Name 							   ptlv_sec80->length,
1693*5113495bSYour Name 							   p_sfft_sec80);
1694*5113495bSYour Name 
1695*5113495bSYour Name 			pfft_sec80 = (struct spectral_phyerr_fft_gen2 *)(
1696*5113495bSYour Name 				((uint8_t *)ptlv_sec80) +
1697*5113495bSYour Name 				sizeof(struct spectral_phyerr_tlv_gen2) +
1698*5113495bSYour Name 				sizeof(struct spectral_phyerr_hdr_gen2) +
1699*5113495bSYour Name 				segid_skiplen);
1700*5113495bSYour Name 
1701*5113495bSYour Name 			qdf_mem_zero(&params, sizeof(params));
1702*5113495bSYour Name 
1703*5113495bSYour Name 			phyerr_info->p_rfqual = p_rfqual;
1704*5113495bSYour Name 			phyerr_info->p_sfft = p_sfft_sec80;
1705*5113495bSYour Name 			phyerr_info->pfft = pfft_sec80;
1706*5113495bSYour Name 			phyerr_info->acs_stats = acs_stats;
1707*5113495bSYour Name 			phyerr_info->tsf64 = tsf64;
1708*5113495bSYour Name 			phyerr_info->seg_id = segid_sec80;
1709*5113495bSYour Name 
1710*5113495bSYour Name 			ret = target_if_spectral_populate_samp_params_gen2(
1711*5113495bSYour Name 							spectral, phyerr_info,
1712*5113495bSYour Name 							&params);
1713*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret)) {
1714*5113495bSYour Name 				spectral_err_rl("Failed to populate SAMP params");
1715*5113495bSYour Name 				goto fail;
1716*5113495bSYour Name 			}
1717*5113495bSYour Name 			ret = target_if_spectral_fill_samp_msg(spectral,
1718*5113495bSYour Name 							       &params);
1719*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret)) {
1720*5113495bSYour Name 				spectral_err_rl("Failed to fill the SAMP msg");
1721*5113495bSYour Name 				goto fail;
1722*5113495bSYour Name 			}
1723*5113495bSYour Name 		}
1724*5113495bSYour Name 	}
1725*5113495bSYour Name 
1726*5113495bSYour Name 	if (spectral_debug_level & DEBUG_SPECTRAL4)
1727*5113495bSYour Name 		spectral_debug_level = DEBUG_SPECTRAL;
1728*5113495bSYour Name 
1729*5113495bSYour Name 	return 0;
1730*5113495bSYour Name 
1731*5113495bSYour Name fail:
1732*5113495bSYour Name 	spectral_err_rl("Error while processing Spectral report");
1733*5113495bSYour Name 
1734*5113495bSYour Name fail_no_print:
1735*5113495bSYour Name 	if (spectral_debug_level & DEBUG_SPECTRAL4)
1736*5113495bSYour Name 		spectral_debug_level = DEBUG_SPECTRAL;
1737*5113495bSYour Name 
1738*5113495bSYour Name 	free_samp_msg_skb(spectral, SPECTRAL_SCAN_MODE_NORMAL);
1739*5113495bSYour Name 	return -EPERM;
1740*5113495bSYour Name }
1741*5113495bSYour Name 
1742*5113495bSYour Name #else
1743*5113495bSYour Name int
target_if_process_phyerr_gen2(struct target_if_spectral * spectral,uint8_t * data,uint32_t datalen,struct target_if_spectral_rfqual_info * p_rfqual,struct target_if_spectral_chan_info * p_chaninfo,uint64_t tsf64,struct target_if_spectral_acs_stats * acs_stats)1744*5113495bSYour Name target_if_process_phyerr_gen2(struct target_if_spectral *spectral,
1745*5113495bSYour Name 			      uint8_t *data,
1746*5113495bSYour Name 			      uint32_t datalen,
1747*5113495bSYour Name 			      struct target_if_spectral_rfqual_info *p_rfqual,
1748*5113495bSYour Name 			      struct target_if_spectral_chan_info *p_chaninfo,
1749*5113495bSYour Name 			      uint64_t tsf64,
1750*5113495bSYour Name 			      struct target_if_spectral_acs_stats *acs_stats)
1751*5113495bSYour Name {
1752*5113495bSYour Name 	/*
1753*5113495bSYour Name 	 * XXX : The classifier do not use all the members of the SAMP
1754*5113495bSYour Name 	 *       message data format.
1755*5113495bSYour Name 	 *       The classifier only depends upon the following parameters
1756*5113495bSYour Name 	 *
1757*5113495bSYour Name 	 *          1. Frequency (freq, msg->freq)
1758*5113495bSYour Name 	 *          2. Spectral RSSI (spectral_rssi,
1759*5113495bSYour Name 	 *          msg->samp_data.spectral_rssi)
1760*5113495bSYour Name 	 *          3. Bin Power Count (bin_pwr_count,
1761*5113495bSYour Name 	 *          msg->samp_data.bin_pwr_count)
1762*5113495bSYour Name 	 *          4. Bin Power values (bin_pwr, msg->samp_data.bin_pwr[0]
1763*5113495bSYour Name 	 *          5. Spectral Timestamp (spectral_tstamp,
1764*5113495bSYour Name 	 *          msg->samp_data.spectral_tstamp)
1765*5113495bSYour Name 	 *          6. MAC Address (macaddr, msg->macaddr)
1766*5113495bSYour Name 	 *
1767*5113495bSYour Name 	 *       This function prepares the params structure and populates it
1768*5113495bSYour Name 	 *       with
1769*5113495bSYour Name 	 *       relevant values, this is in turn passed to
1770*5113495bSYour Name 	 *       spectral_create_samp_msg()
1771*5113495bSYour Name 	 *       to prepare fully formatted Spectral SAMP message
1772*5113495bSYour Name 	 *
1773*5113495bSYour Name 	 *       XXX : Need to verify
1774*5113495bSYour Name 	 *          1. Order of FFT bin values
1775*5113495bSYour Name 	 *
1776*5113495bSYour Name 	 */
1777*5113495bSYour Name 
1778*5113495bSYour Name 	struct target_if_samp_msg_params params;
1779*5113495bSYour Name 	struct spectral_search_fft_info_gen2 search_fft_info;
1780*5113495bSYour Name 	struct spectral_search_fft_info_gen2 *p_sfft = &search_fft_info;
1781*5113495bSYour Name 	struct spectral_search_fft_info_gen2 search_fft_info_sec80;
1782*5113495bSYour Name 	struct spectral_search_fft_info_gen2 *p_sfft_sec80 =
1783*5113495bSYour Name 		&search_fft_info_sec80;
1784*5113495bSYour Name 	uint32_t segid_skiplen = 0;
1785*5113495bSYour Name 
1786*5113495bSYour Name 	int8_t rssi_up = 0;
1787*5113495bSYour Name 	int8_t rssi_low = 0;
1788*5113495bSYour Name 
1789*5113495bSYour Name 	int8_t chn_idx_highest_enabled = 0;
1790*5113495bSYour Name 	int8_t chn_idx_lowest_enabled = 0;
1791*5113495bSYour Name 
1792*5113495bSYour Name 	uint8_t control_rssi = 0;
1793*5113495bSYour Name 	uint8_t extension_rssi = 0;
1794*5113495bSYour Name 	uint8_t combined_rssi = 0;
1795*5113495bSYour Name 
1796*5113495bSYour Name 	uint32_t tstamp = 0;
1797*5113495bSYour Name 
1798*5113495bSYour Name 	struct target_if_spectral_ops *p_sops =
1799*5113495bSYour Name 		GET_TARGET_IF_SPECTRAL_OPS(spectral);
1800*5113495bSYour Name 
1801*5113495bSYour Name 	struct spectral_phyerr_tlv_gen2 *ptlv =
1802*5113495bSYour Name 		(struct spectral_phyerr_tlv_gen2 *)data;
1803*5113495bSYour Name 	struct spectral_phyerr_tlv_gen2 *ptlv_sec80 = NULL;
1804*5113495bSYour Name 	struct spectral_phyerr_fft_gen2 *pfft = NULL;
1805*5113495bSYour Name 	struct spectral_phyerr_fft_gen2 *pfft_sec80 = NULL;
1806*5113495bSYour Name 
1807*5113495bSYour Name 	uint8_t segid = 0;
1808*5113495bSYour Name 	uint8_t segid_sec80 = 0;
1809*5113495bSYour Name 	enum phy_ch_width ch_width =
1810*5113495bSYour Name 				spectral->ch_width[SPECTRAL_SCAN_MODE_NORMAL];
1811*5113495bSYour Name 
1812*5113495bSYour Name 	if (spectral->is_160_format)
1813*5113495bSYour Name 		segid_skiplen = sizeof(SPECTRAL_SEGID_INFO);
1814*5113495bSYour Name 
1815*5113495bSYour Name 	pfft = (struct spectral_phyerr_fft_gen2 *)(
1816*5113495bSYour Name 			data +
1817*5113495bSYour Name 			sizeof(struct spectral_phyerr_tlv_gen2) +
1818*5113495bSYour Name 			sizeof(struct spectral_phyerr_hdr_gen2) +
1819*5113495bSYour Name 			segid_skiplen);
1820*5113495bSYour Name 
1821*5113495bSYour Name 	/*
1822*5113495bSYour Name 	 * XXX Extend SPECTRAL_DPRINTK() to use spectral_debug_level,
1823*5113495bSYour Name 	 * and use this facility inside spectral_dump_phyerr_data()
1824*5113495bSYour Name 	 * and supporting functions.
1825*5113495bSYour Name 	 */
1826*5113495bSYour Name 	if (spectral_debug_level & DEBUG_SPECTRAL2)
1827*5113495bSYour Name 		target_if_spectral_dump_phyerr_data_gen2(
1828*5113495bSYour Name 					data, datalen,
1829*5113495bSYour Name 					spectral->is_160_format);
1830*5113495bSYour Name 
1831*5113495bSYour Name 	if (spectral_debug_level & DEBUG_SPECTRAL4) {
1832*5113495bSYour Name 		target_if_spectral_dump_phyerr_data_gen2(
1833*5113495bSYour Name 					data, datalen,
1834*5113495bSYour Name 					spectral->is_160_format);
1835*5113495bSYour Name 		spectral_debug_level = DEBUG_SPECTRAL;
1836*5113495bSYour Name 	}
1837*5113495bSYour Name 
1838*5113495bSYour Name 	if (ptlv->signature != SPECTRAL_PHYERR_SIGNATURE_GEN2) {
1839*5113495bSYour Name 		/*
1840*5113495bSYour Name 		 * EV# 118023: We tentatively disable the below print
1841*5113495bSYour Name 		 * and provide stats instead.
1842*5113495bSYour Name 		 */
1843*5113495bSYour Name 		spectral->diag_stats.spectral_mismatch++;
1844*5113495bSYour Name 		return -EPERM;
1845*5113495bSYour Name 	}
1846*5113495bSYour Name 
1847*5113495bSYour Name 	OS_MEMZERO(&params, sizeof(params));
1848*5113495bSYour Name 	/* Gen 2 only supports normal Spectral scan currently */
1849*5113495bSYour Name 	params.smode = SPECTRAL_SCAN_MODE_NORMAL;
1850*5113495bSYour Name 
1851*5113495bSYour Name 	if (ptlv->tag == TLV_TAG_SEARCH_FFT_REPORT_GEN2) {
1852*5113495bSYour Name 		if (spectral->is_160_format) {
1853*5113495bSYour Name 			segid = *((SPECTRAL_SEGID_INFO *)(
1854*5113495bSYour Name 				  (uint8_t *)ptlv +
1855*5113495bSYour Name 				  sizeof(struct spectral_phyerr_tlv_gen2) +
1856*5113495bSYour Name 				  sizeof(struct spectral_phyerr_hdr_gen2)));
1857*5113495bSYour Name 
1858*5113495bSYour Name 			if (segid != 0) {
1859*5113495bSYour Name 				struct spectral_diag_stats *p_diag_stats =
1860*5113495bSYour Name 					&spectral->diag_stats;
1861*5113495bSYour Name 				p_diag_stats->spectral_vhtseg1id_mismatch++;
1862*5113495bSYour Name 				return -EPERM;
1863*5113495bSYour Name 			}
1864*5113495bSYour Name 		}
1865*5113495bSYour Name 
1866*5113495bSYour Name 		target_if_process_sfft_report_gen2(ptlv, ptlv->length,
1867*5113495bSYour Name 						   &search_fft_info);
1868*5113495bSYour Name 
1869*5113495bSYour Name 		tstamp = p_sops->get_tsf64(spectral) & SPECTRAL_TSMASK;
1870*5113495bSYour Name 
1871*5113495bSYour Name 		combined_rssi = p_rfqual->rssi_comb;
1872*5113495bSYour Name 
1873*5113495bSYour Name 		if (spectral->upper_is_control)
1874*5113495bSYour Name 			rssi_up = control_rssi;
1875*5113495bSYour Name 		else
1876*5113495bSYour Name 			rssi_up = extension_rssi;
1877*5113495bSYour Name 
1878*5113495bSYour Name 		if (spectral->lower_is_control)
1879*5113495bSYour Name 			rssi_low = control_rssi;
1880*5113495bSYour Name 		else
1881*5113495bSYour Name 			rssi_low = extension_rssi;
1882*5113495bSYour Name 
1883*5113495bSYour Name 		params.rssi = p_rfqual->rssi_comb;
1884*5113495bSYour Name 		params.lower_rssi = rssi_low;
1885*5113495bSYour Name 		params.upper_rssi = rssi_up;
1886*5113495bSYour Name 
1887*5113495bSYour Name 		if (spectral->sc_spectral_noise_pwr_cal) {
1888*5113495bSYour Name 			params.chain_ctl_rssi[0] =
1889*5113495bSYour Name 			    p_rfqual->pc_rssi_info[0].rssi_pri20;
1890*5113495bSYour Name 			params.chain_ctl_rssi[1] =
1891*5113495bSYour Name 			    p_rfqual->pc_rssi_info[1].rssi_pri20;
1892*5113495bSYour Name 			params.chain_ctl_rssi[2] =
1893*5113495bSYour Name 			    p_rfqual->pc_rssi_info[2].rssi_pri20;
1894*5113495bSYour Name 			params.chain_ext_rssi[0] =
1895*5113495bSYour Name 			    p_rfqual->pc_rssi_info[0].rssi_sec20;
1896*5113495bSYour Name 			params.chain_ext_rssi[1] =
1897*5113495bSYour Name 			    p_rfqual->pc_rssi_info[1].rssi_sec20;
1898*5113495bSYour Name 			params.chain_ext_rssi[2] =
1899*5113495bSYour Name 			    p_rfqual->pc_rssi_info[2].rssi_sec20;
1900*5113495bSYour Name 		}
1901*5113495bSYour Name 
1902*5113495bSYour Name 		/*
1903*5113495bSYour Name 		 * XXX : This actually depends on the programmed chain mask
1904*5113495bSYour Name 		 *       This value decides the per-chain enable mask to select
1905*5113495bSYour Name 		 *       the input ADC for search FTT.
1906*5113495bSYour Name 		 *       For modes upto VHT80, if more than one chain is
1907*5113495bSYour Name 		 *       enabled, the max valid chain
1908*5113495bSYour Name 		 *       is used. LSB corresponds to chain zero.
1909*5113495bSYour Name 		 *       For VHT80_80 and VHT160, the lowest enabled chain is
1910*5113495bSYour Name 		 *       used for primary
1911*5113495bSYour Name 		 *       detection and highest enabled chain is used for
1912*5113495bSYour Name 		 *       secondary detection.
1913*5113495bSYour Name 		 *
1914*5113495bSYour Name 		 * XXX : The current algorithm do not use these control and
1915*5113495bSYour Name 		 *       extension channel
1916*5113495bSYour Name 		 *       Instead, it just relies on the combined RSSI values
1917*5113495bSYour Name 		 *       only.
1918*5113495bSYour Name 		 *       For fool-proof detection algorithm, we should take
1919*5113495bSYour Name 		 *       these RSSI values in to account.
1920*5113495bSYour Name 		 *       This is marked for future enhancements.
1921*5113495bSYour Name 		 */
1922*5113495bSYour Name 		chn_idx_highest_enabled =
1923*5113495bSYour Name 		   ((spectral->params[params.smode].ss_chn_mask & 0x8) ? 3 :
1924*5113495bSYour Name 		    (spectral->params[params.smode].ss_chn_mask & 0x4) ? 2 :
1925*5113495bSYour Name 		    (spectral->params[params.smode].ss_chn_mask & 0x2) ? 1 : 0);
1926*5113495bSYour Name 		chn_idx_lowest_enabled =
1927*5113495bSYour Name 		   ((spectral->params[params.smode].ss_chn_mask & 0x1) ? 0 :
1928*5113495bSYour Name 		    (spectral->params[params.smode].ss_chn_mask & 0x2) ? 1 :
1929*5113495bSYour Name 		    (spectral->params[params.smode].ss_chn_mask & 0x4) ? 2 : 3);
1930*5113495bSYour Name 		control_rssi = (uint8_t)
1931*5113495bSYour Name 		    p_rfqual->pc_rssi_info[chn_idx_highest_enabled].rssi_pri20;
1932*5113495bSYour Name 		extension_rssi = (uint8_t)
1933*5113495bSYour Name 		    p_rfqual->pc_rssi_info[chn_idx_highest_enabled].rssi_sec20;
1934*5113495bSYour Name 
1935*5113495bSYour Name 		params.bwinfo = 0;
1936*5113495bSYour Name 		params.tstamp = 0;
1937*5113495bSYour Name 		params.max_mag = p_sfft->peak_mag;
1938*5113495bSYour Name 
1939*5113495bSYour Name 		params.max_index = p_sfft->peak_inx;
1940*5113495bSYour Name 		params.max_exp = 0;
1941*5113495bSYour Name 		params.peak = 0;
1942*5113495bSYour Name 		params.bin_pwr_data = (uint8_t *)pfft;
1943*5113495bSYour Name 		params.freq = p_sops->get_current_channel(spectral,
1944*5113495bSYour Name 							  params.smode);
1945*5113495bSYour Name 		params.freq_loading = 0;
1946*5113495bSYour Name 
1947*5113495bSYour Name 		params.interf_list.count = 0;
1948*5113495bSYour Name 		params.max_lower_index = 0;
1949*5113495bSYour Name 		params.max_upper_index = 0;
1950*5113495bSYour Name 		params.nb_lower = 0;
1951*5113495bSYour Name 		params.nb_upper = 0;
1952*5113495bSYour Name 		/*
1953*5113495bSYour Name 		 * For modes upto VHT80, the noise floor is populated with the
1954*5113495bSYour Name 		 * one corresponding
1955*5113495bSYour Name 		 * to the highest enabled antenna chain
1956*5113495bSYour Name 		 */
1957*5113495bSYour Name 		params.noise_floor =
1958*5113495bSYour Name 		    p_rfqual->noise_floor[chn_idx_highest_enabled];
1959*5113495bSYour Name 		params.datalen = ptlv->length;
1960*5113495bSYour Name 		params.pwr_count = ptlv->length -
1961*5113495bSYour Name 		    sizeof(struct spectral_phyerr_hdr_gen2) - segid_skiplen;
1962*5113495bSYour Name 		params.tstamp = (tsf64 & SPECTRAL_TSMASK);
1963*5113495bSYour Name 
1964*5113495bSYour Name 		acs_stats->ctrl_nf = params.noise_floor;
1965*5113495bSYour Name 		acs_stats->ext_nf = params.noise_floor;
1966*5113495bSYour Name 		acs_stats->nfc_ctl_rssi = control_rssi;
1967*5113495bSYour Name 		acs_stats->nfc_ext_rssi = extension_rssi;
1968*5113495bSYour Name 
1969*5113495bSYour Name 		if (spectral->is_160_format &&
1970*5113495bSYour Name 		    is_ch_width_160_or_80p80(ch_width)) {
1971*5113495bSYour Name 			/*
1972*5113495bSYour Name 			 * We expect to see one more Search FFT report, and it
1973*5113495bSYour Name 			 * should be equal in size to the current one.
1974*5113495bSYour Name 			 */
1975*5113495bSYour Name 			if (datalen < (
1976*5113495bSYour Name 				2 * (
1977*5113495bSYour Name 				sizeof(struct spectral_phyerr_tlv_gen2) +
1978*5113495bSYour Name 				ptlv->length))) {
1979*5113495bSYour Name 				struct spectral_diag_stats *p_diag_stats =
1980*5113495bSYour Name 					&spectral->diag_stats;
1981*5113495bSYour Name 				p_diag_stats->spectral_sec80_sfft_insufflen++;
1982*5113495bSYour Name 				return -EPERM;
1983*5113495bSYour Name 			}
1984*5113495bSYour Name 
1985*5113495bSYour Name 			ptlv_sec80 = (struct spectral_phyerr_tlv_gen2 *)(
1986*5113495bSYour Name 				      data +
1987*5113495bSYour Name 				      sizeof(struct spectral_phyerr_tlv_gen2) +
1988*5113495bSYour Name 				      ptlv->length);
1989*5113495bSYour Name 
1990*5113495bSYour Name 			if (ptlv_sec80->signature !=
1991*5113495bSYour Name 			    SPECTRAL_PHYERR_SIGNATURE_GEN2) {
1992*5113495bSYour Name 				spectral->diag_stats.spectral_mismatch++;
1993*5113495bSYour Name 				return -EPERM;
1994*5113495bSYour Name 			}
1995*5113495bSYour Name 
1996*5113495bSYour Name 			if (ptlv_sec80->tag != TLV_TAG_SEARCH_FFT_REPORT_GEN2) {
1997*5113495bSYour Name 				spectral->diag_stats.spectral_no_sec80_sfft++;
1998*5113495bSYour Name 				return -EPERM;
1999*5113495bSYour Name 			}
2000*5113495bSYour Name 
2001*5113495bSYour Name 			segid_sec80 = *((SPECTRAL_SEGID_INFO *)(
2002*5113495bSYour Name 				(uint8_t *)ptlv_sec80 +
2003*5113495bSYour Name 				sizeof(struct spectral_phyerr_tlv_gen2) +
2004*5113495bSYour Name 				sizeof(struct spectral_phyerr_hdr_gen2)));
2005*5113495bSYour Name 
2006*5113495bSYour Name 			if (segid_sec80 != 1) {
2007*5113495bSYour Name 				struct spectral_diag_stats *p_diag_stats =
2008*5113495bSYour Name 					&spectral->diag_stats;
2009*5113495bSYour Name 				p_diag_stats->spectral_vhtseg2id_mismatch++;
2010*5113495bSYour Name 				return -EPERM;
2011*5113495bSYour Name 			}
2012*5113495bSYour Name 
2013*5113495bSYour Name 			params.vhtop_ch_freq_seg1 = p_chaninfo->center_freq1;
2014*5113495bSYour Name 			params.vhtop_ch_freq_seg2 = p_chaninfo->center_freq2;
2015*5113495bSYour Name 
2016*5113495bSYour Name 			target_if_process_sfft_report_gen2(
2017*5113495bSYour Name 				ptlv_sec80,
2018*5113495bSYour Name 				ptlv_sec80->length,
2019*5113495bSYour Name 				&search_fft_info_sec80);
2020*5113495bSYour Name 
2021*5113495bSYour Name 			pfft_sec80 = (struct spectral_phyerr_fft_gen2 *)(
2022*5113495bSYour Name 				((uint8_t *)ptlv_sec80) +
2023*5113495bSYour Name 				sizeof(struct spectral_phyerr_tlv_gen2) +
2024*5113495bSYour Name 				sizeof(struct spectral_phyerr_hdr_gen2) +
2025*5113495bSYour Name 				segid_skiplen);
2026*5113495bSYour Name 
2027*5113495bSYour Name 			/* XXX: Confirm. TBD at SoD. */
2028*5113495bSYour Name 			params.rssi_sec80 = p_rfqual->rssi_comb;
2029*5113495bSYour Name 			if (spectral->is_sec80_rssi_war_required)
2030*5113495bSYour Name 				params.rssi_sec80 =
2031*5113495bSYour Name 				    target_if_get_combrssi_sec80_seg_gen2
2032*5113495bSYour Name 				    (spectral, &search_fft_info_sec80);
2033*5113495bSYour Name 			/* XXX: Determine dynamically. TBD at SoD. */
2034*5113495bSYour Name 			/*
2035*5113495bSYour Name 			 * For VHT80_80/VHT160, the noise floor for primary
2036*5113495bSYour Name 			 * 80MHz segment is populated with the
2037*5113495bSYour Name 			 * lowest enabled antenna chain and the noise floor for
2038*5113495bSYour Name 			 * secondary 80MHz segment is populated
2039*5113495bSYour Name 			 * with the highest enabled antenna chain
2040*5113495bSYour Name 			 */
2041*5113495bSYour Name 			params.noise_floor_sec80 =
2042*5113495bSYour Name 			    p_rfqual->noise_floor[chn_idx_highest_enabled];
2043*5113495bSYour Name 			params.noise_floor =
2044*5113495bSYour Name 			    p_rfqual->noise_floor[chn_idx_lowest_enabled];
2045*5113495bSYour Name 
2046*5113495bSYour Name 			params.max_mag_sec80 = p_sfft_sec80->peak_mag;
2047*5113495bSYour Name 			params.max_index_sec80 = p_sfft_sec80->peak_inx;
2048*5113495bSYour Name 			/* XXX Does this definition of datalen *still hold? */
2049*5113495bSYour Name 			params.datalen_sec80 = ptlv_sec80->length;
2050*5113495bSYour Name 			params.pwr_count_sec80 =
2051*5113495bSYour Name 			    ptlv_sec80->length -
2052*5113495bSYour Name 			    sizeof(struct spectral_phyerr_hdr_gen2) -
2053*5113495bSYour Name 			    segid_skiplen;
2054*5113495bSYour Name 			params.bin_pwr_data_sec80 = (uint8_t *)pfft_sec80;
2055*5113495bSYour Name 		}
2056*5113495bSYour Name 		qdf_mem_copy(&params.classifier_params,
2057*5113495bSYour Name 			     &spectral->classifier_params,
2058*5113495bSYour Name 			     sizeof(struct spectral_classifier_params));
2059*5113495bSYour Name 
2060*5113495bSYour Name 		target_if_spectral_log_SAMP_param(&params);
2061*5113495bSYour Name 		target_if_spectral_create_samp_msg(spectral, &params);
2062*5113495bSYour Name 	}
2063*5113495bSYour Name 
2064*5113495bSYour Name 	return 0;
2065*5113495bSYour Name }
2066*5113495bSYour Name #endif /* OPTIMIZED_SAMP_MESSAGE */
2067*5113495bSYour Name 
2068*5113495bSYour Name int
target_if_spectral_dump_hdr_gen2(struct spectral_phyerr_hdr_gen2 * phdr)2069*5113495bSYour Name target_if_spectral_dump_hdr_gen2(struct spectral_phyerr_hdr_gen2 *phdr)
2070*5113495bSYour Name {
2071*5113495bSYour Name 	uint32_t a = 0;
2072*5113495bSYour Name 	uint32_t b = 0;
2073*5113495bSYour Name 
2074*5113495bSYour Name 	qdf_mem_copy(&a, (uint8_t *)phdr, sizeof(int));
2075*5113495bSYour Name 	qdf_mem_copy(&b,
2076*5113495bSYour Name 		     (uint8_t *)((uint8_t *)phdr + sizeof(int)),
2077*5113495bSYour Name 		     sizeof(int));
2078*5113495bSYour Name 
2079*5113495bSYour Name 	spectral_debug("SPECTRAL : HEADER A 0x%x (%d)", a, a);
2080*5113495bSYour Name 	spectral_debug("SPECTRAL : HEADER B 0x%x (%d)", b, b);
2081*5113495bSYour Name 	return 0;
2082*5113495bSYour Name }
2083*5113495bSYour Name 
2084*5113495bSYour Name int8_t
target_if_get_combrssi_sec80_seg_gen2(struct target_if_spectral * spectral,struct spectral_search_fft_info_gen2 * p_sfft_sec80)2085*5113495bSYour Name target_if_get_combrssi_sec80_seg_gen2(
2086*5113495bSYour Name 	struct target_if_spectral *spectral,
2087*5113495bSYour Name 	struct spectral_search_fft_info_gen2 *p_sfft_sec80)
2088*5113495bSYour Name {
2089*5113495bSYour Name 	uint32_t avgpwr_db = 0;
2090*5113495bSYour Name 	uint32_t total_gain_db = 0;
2091*5113495bSYour Name 	uint32_t offset = 0;
2092*5113495bSYour Name 	int8_t comb_rssi = 0;
2093*5113495bSYour Name 
2094*5113495bSYour Name 	/* Obtain required parameters for algorithm from search FFT report */
2095*5113495bSYour Name 	avgpwr_db = p_sfft_sec80->avgpwr_db;
2096*5113495bSYour Name 	total_gain_db = p_sfft_sec80->total_gain_info;
2097*5113495bSYour Name 
2098*5113495bSYour Name 	/* Calculate offset */
2099*5113495bSYour Name 	offset = target_if_get_offset_swar_sec80(
2100*5113495bSYour Name 			spectral->ch_width[SPECTRAL_SCAN_MODE_NORMAL]);
2101*5113495bSYour Name 
2102*5113495bSYour Name 	/* Calculate RSSI */
2103*5113495bSYour Name 	comb_rssi = ((avgpwr_db - total_gain_db) + offset);
2104*5113495bSYour Name 
2105*5113495bSYour Name 	return comb_rssi;
2106*5113495bSYour Name }
2107*5113495bSYour Name 
2108*5113495bSYour Name int
target_if_spectral_dump_tlv_gen2(struct spectral_phyerr_tlv_gen2 * ptlv,bool is_160_format)2109*5113495bSYour Name target_if_spectral_dump_tlv_gen2(
2110*5113495bSYour Name 	struct spectral_phyerr_tlv_gen2 *ptlv, bool is_160_format)
2111*5113495bSYour Name {
2112*5113495bSYour Name 	int ret = 0;
2113*5113495bSYour Name 
2114*5113495bSYour Name 	/*
2115*5113495bSYour Name 	 * TODO : Do not delete the following print
2116*5113495bSYour Name 	 *        The scripts used to validate Spectral depend on this Print
2117*5113495bSYour Name 	 */
2118*5113495bSYour Name 	spectral_debug("SPECTRAL : TLV Length is 0x%x (%d)",
2119*5113495bSYour Name 		       ptlv->length, ptlv->length);
2120*5113495bSYour Name 
2121*5113495bSYour Name 	switch (ptlv->tag) {
2122*5113495bSYour Name 	case TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN2:
2123*5113495bSYour Name 		ret =
2124*5113495bSYour Name 		    target_if_dump_summary_report_gen2(
2125*5113495bSYour Name 			ptlv, ptlv->length, is_160_format);
2126*5113495bSYour Name 		break;
2127*5113495bSYour Name 
2128*5113495bSYour Name 	case TLV_TAG_SEARCH_FFT_REPORT_GEN2:
2129*5113495bSYour Name 		ret =
2130*5113495bSYour Name 		    target_if_dump_sfft_report_gen2(ptlv, ptlv->length,
2131*5113495bSYour Name 						    is_160_format);
2132*5113495bSYour Name 		break;
2133*5113495bSYour Name 
2134*5113495bSYour Name 	case TLV_TAG_ADC_REPORT_GEN2:
2135*5113495bSYour Name 		ret = target_if_dump_adc_report_gen2(ptlv, ptlv->length);
2136*5113495bSYour Name 		break;
2137*5113495bSYour Name 
2138*5113495bSYour Name 	default:
2139*5113495bSYour Name 		spectral_warn("INVALID TLV");
2140*5113495bSYour Name 		ret = -1;
2141*5113495bSYour Name 		break;
2142*5113495bSYour Name 	}
2143*5113495bSYour Name 
2144*5113495bSYour Name 	return ret;
2145*5113495bSYour Name }
2146*5113495bSYour Name 
2147*5113495bSYour Name int
target_if_spectral_dump_phyerr_data_gen2(uint8_t * data,uint32_t datalen,bool is_160_format)2148*5113495bSYour Name target_if_spectral_dump_phyerr_data_gen2(uint8_t *data, uint32_t datalen,
2149*5113495bSYour Name 					 bool is_160_format)
2150*5113495bSYour Name {
2151*5113495bSYour Name 	struct spectral_phyerr_tlv_gen2 *ptlv = NULL;
2152*5113495bSYour Name 	uint32_t bytes_processed = 0;
2153*5113495bSYour Name 	uint32_t bytes_remaining = datalen;
2154*5113495bSYour Name 	uint32_t curr_tlv_complete_size = 0;
2155*5113495bSYour Name 
2156*5113495bSYour Name 	if (datalen < sizeof(struct spectral_phyerr_tlv_gen2)) {
2157*5113495bSYour Name 		spectral_err("Total PHY error data length %u too short to contain any TLVs",
2158*5113495bSYour Name 			     datalen);
2159*5113495bSYour Name 		return -EPERM;
2160*5113495bSYour Name 	}
2161*5113495bSYour Name 
2162*5113495bSYour Name 	while (bytes_processed < datalen) {
2163*5113495bSYour Name 		if (bytes_remaining < sizeof(struct spectral_phyerr_tlv_gen2)) {
2164*5113495bSYour Name 			spectral_err("Remaining PHY error data length %u too short to contain a TLV",
2165*5113495bSYour Name 				     bytes_remaining);
2166*5113495bSYour Name 			return -EPERM;
2167*5113495bSYour Name 		}
2168*5113495bSYour Name 
2169*5113495bSYour Name 		ptlv = (struct spectral_phyerr_tlv_gen2 *)(data +
2170*5113495bSYour Name 							   bytes_processed);
2171*5113495bSYour Name 
2172*5113495bSYour Name 		if (ptlv->signature != SPECTRAL_PHYERR_SIGNATURE_GEN2) {
2173*5113495bSYour Name 			spectral_err("Invalid signature 0x%x!",
2174*5113495bSYour Name 				     ptlv->signature);
2175*5113495bSYour Name 			return -EPERM;
2176*5113495bSYour Name 		}
2177*5113495bSYour Name 
2178*5113495bSYour Name 		curr_tlv_complete_size =
2179*5113495bSYour Name 			sizeof(struct spectral_phyerr_tlv_gen2) +
2180*5113495bSYour Name 			ptlv->length;
2181*5113495bSYour Name 
2182*5113495bSYour Name 		if (curr_tlv_complete_size > bytes_remaining) {
2183*5113495bSYour Name 			spectral_err("TLV size %d greater than number of bytes remaining %d",
2184*5113495bSYour Name 				     curr_tlv_complete_size, bytes_remaining);
2185*5113495bSYour Name 			return -EPERM;
2186*5113495bSYour Name 		}
2187*5113495bSYour Name 
2188*5113495bSYour Name 		if (target_if_spectral_dump_tlv_gen2(ptlv, is_160_format) == -1)
2189*5113495bSYour Name 			return -EPERM;
2190*5113495bSYour Name 
2191*5113495bSYour Name 		bytes_processed += curr_tlv_complete_size;
2192*5113495bSYour Name 		bytes_remaining = datalen - bytes_processed;
2193*5113495bSYour Name 	}
2194*5113495bSYour Name 
2195*5113495bSYour Name 	return 0;
2196*5113495bSYour Name }
2197*5113495bSYour Name 
2198*5113495bSYour Name QDF_STATUS
target_if_spectral_copy_fft_bins(struct target_if_spectral * spectral,const void * src_fft_buf,void * dest_fft_buf,uint32_t fft_bin_count,uint32_t * bytes_copied,uint16_t pwr_format)2199*5113495bSYour Name target_if_spectral_copy_fft_bins(struct target_if_spectral *spectral,
2200*5113495bSYour Name 				 const void *src_fft_buf,
2201*5113495bSYour Name 				 void *dest_fft_buf,
2202*5113495bSYour Name 				 uint32_t fft_bin_count,
2203*5113495bSYour Name 				 uint32_t *bytes_copied,
2204*5113495bSYour Name 				 uint16_t pwr_format)
2205*5113495bSYour Name {
2206*5113495bSYour Name 	uint16_t idx, dword_idx, fft_bin_idx;
2207*5113495bSYour Name 	uint8_t num_bins_per_dword, hw_fft_bin_width_bits;
2208*5113495bSYour Name 	uint32_t num_dwords;
2209*5113495bSYour Name 	uint16_t fft_bin_val;
2210*5113495bSYour Name 	struct spectral_report_params *rparams;
2211*5113495bSYour Name 	const uint32_t *dword_ptr;
2212*5113495bSYour Name 	uint32_t dword;
2213*5113495bSYour Name 	uint8_t *fft_bin_buf;
2214*5113495bSYour Name 
2215*5113495bSYour Name 	*bytes_copied = 0;
2216*5113495bSYour Name 
2217*5113495bSYour Name 	if (!spectral) {
2218*5113495bSYour Name 		spectral_err("spectral lmac object is NULL");
2219*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
2220*5113495bSYour Name 	}
2221*5113495bSYour Name 
2222*5113495bSYour Name 	if (!src_fft_buf) {
2223*5113495bSYour Name 		spectral_err("source fft bin buffer is NULL");
2224*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
2225*5113495bSYour Name 	}
2226*5113495bSYour Name 
2227*5113495bSYour Name 	if (!dest_fft_buf) {
2228*5113495bSYour Name 		spectral_err("destination fft bin buffer is NULL");
2229*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
2230*5113495bSYour Name 	}
2231*5113495bSYour Name 
2232*5113495bSYour Name 	rparams = &spectral->rparams;
2233*5113495bSYour Name 	num_bins_per_dword = SPECTRAL_DWORD_SIZE / rparams->hw_fft_bin_width;
2234*5113495bSYour Name 	num_dwords = fft_bin_count / num_bins_per_dword;
2235*5113495bSYour Name 	hw_fft_bin_width_bits = rparams->hw_fft_bin_width * QDF_CHAR_BIT;
2236*5113495bSYour Name 
2237*5113495bSYour Name 	fft_bin_idx = 0;
2238*5113495bSYour Name 	dword_ptr = src_fft_buf;
2239*5113495bSYour Name 	fft_bin_buf = dest_fft_buf;
2240*5113495bSYour Name 	for (dword_idx = 0; dword_idx < num_dwords; dword_idx++) {
2241*5113495bSYour Name 		dword = *dword_ptr++; /* Read a DWORD */
2242*5113495bSYour Name 		for (idx = 0; idx < num_bins_per_dword; idx++) {
2243*5113495bSYour Name 			/**
2244*5113495bSYour Name 			 * If we use QDF_GET_BITS, when hw_fft_bin_width_bits is
2245*5113495bSYour Name 			 * 32, on certain platforms, we could end up doing a
2246*5113495bSYour Name 			 * 32-bit left shift operation on 32-bit constant
2247*5113495bSYour Name 			 * integer '1'. As per C standard, result of shifting an
2248*5113495bSYour Name 			 * operand by a count greater than or equal to width
2249*5113495bSYour Name 			 * (in bits) of the operand is undefined.
2250*5113495bSYour Name 			 * If we use QDF_GET_BITS_64, we can avoid that.
2251*5113495bSYour Name 			 */
2252*5113495bSYour Name 			fft_bin_val = (uint16_t)QDF_GET_BITS64(
2253*5113495bSYour Name 					dword,
2254*5113495bSYour Name 					idx * hw_fft_bin_width_bits,
2255*5113495bSYour Name 					hw_fft_bin_width_bits);
2256*5113495bSYour Name 
2257*5113495bSYour Name 			fft_bin_buf[fft_bin_idx++] =
2258*5113495bSYour Name 				clamp_fft_bin_value(fft_bin_val, pwr_format);
2259*5113495bSYour Name 		}
2260*5113495bSYour Name 	}
2261*5113495bSYour Name 
2262*5113495bSYour Name 	*bytes_copied = num_dwords *  SPECTRAL_DWORD_SIZE;
2263*5113495bSYour Name 
2264*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
2265*5113495bSYour Name }
2266*5113495bSYour Name 
2267*5113495bSYour Name #ifdef DIRECT_BUF_RX_ENABLE
2268*5113495bSYour Name /**
2269*5113495bSYour Name  * target_if_get_spectral_mode() - Get Spectral scan mode corresponding to a
2270*5113495bSYour Name  * detector id
2271*5113495bSYour Name  * @detector_id: detector id in the Spectral report
2272*5113495bSYour Name  * @rparams: pointer to report params object
2273*5113495bSYour Name  *
2274*5113495bSYour Name  * Helper API to get Spectral scan mode from the detector ID. This mapping is
2275*5113495bSYour Name  * target specific.
2276*5113495bSYour Name  *
2277*5113495bSYour Name  * Return: Spectral scan mode
2278*5113495bSYour Name  */
2279*5113495bSYour Name static enum spectral_scan_mode
target_if_get_spectral_mode(enum spectral_detector_id detector_id,struct spectral_report_params * rparams)2280*5113495bSYour Name target_if_get_spectral_mode(enum spectral_detector_id detector_id,
2281*5113495bSYour Name 			    struct spectral_report_params *rparams)
2282*5113495bSYour Name {
2283*5113495bSYour Name 	if (detector_id >= SPECTRAL_DETECTOR_ID_MAX) {
2284*5113495bSYour Name 		spectral_err_rl("Invalid detector id %d", detector_id);
2285*5113495bSYour Name 		return SPECTRAL_SCAN_MODE_INVALID;
2286*5113495bSYour Name 	}
2287*5113495bSYour Name 
2288*5113495bSYour Name 	return rparams->detid_mode_table[detector_id];
2289*5113495bSYour Name }
2290*5113495bSYour Name 
2291*5113495bSYour Name /**
2292*5113495bSYour Name  * target_if_spectral_get_bin_count_after_len_adj() - Get number of FFT bins in
2293*5113495bSYour Name  * Spectral FFT report
2294*5113495bSYour Name  * @fft_bin_len: FFT bin length reported by target
2295*5113495bSYour Name  * @rpt_mode: Spectral report mode
2296*5113495bSYour Name  * @swar: Spectral FFT bin length adjustments SWAR parameters
2297*5113495bSYour Name  * @fft_bin_size: Size of one FFT bin in bytes
2298*5113495bSYour Name  *
2299*5113495bSYour Name  * Get actual number of FFT bins in the FFT report after adjusting the length
2300*5113495bSYour Name  * by applying the SWARs for getting correct length.
2301*5113495bSYour Name  *
2302*5113495bSYour Name  * Return: FFT bin count
2303*5113495bSYour Name  */
2304*5113495bSYour Name static size_t
target_if_spectral_get_bin_count_after_len_adj(size_t fft_bin_len,uint8_t rpt_mode,struct spectral_fft_bin_len_adj_swar * swar,size_t * fft_bin_size)2305*5113495bSYour Name target_if_spectral_get_bin_count_after_len_adj(
2306*5113495bSYour Name 				size_t fft_bin_len, uint8_t rpt_mode,
2307*5113495bSYour Name 				struct spectral_fft_bin_len_adj_swar *swar,
2308*5113495bSYour Name 				size_t *fft_bin_size)
2309*5113495bSYour Name {
2310*5113495bSYour Name 	size_t fft_bin_count = fft_bin_len;
2311*5113495bSYour Name 
2312*5113495bSYour Name 	if (rpt_mode == 1 && swar->null_fftbin_adj) {
2313*5113495bSYour Name 		/*
2314*5113495bSYour Name 		 * No FFT bins are expected. Explicitly set FFT bin
2315*5113495bSYour Name 		 * count to 0.
2316*5113495bSYour Name 		 */
2317*5113495bSYour Name 		fft_bin_count = 0;
2318*5113495bSYour Name 		*fft_bin_size = 0;
2319*5113495bSYour Name 	} else {
2320*5113495bSYour Name 		/*
2321*5113495bSYour Name 		 * Divide fft bin length by appropriate factor depending
2322*5113495bSYour Name 		 * on the value of fftbin_size_war.
2323*5113495bSYour Name 		 */
2324*5113495bSYour Name 		switch (swar->fftbin_size_war) {
2325*5113495bSYour Name 		case SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE:
2326*5113495bSYour Name 			fft_bin_count >>= 2;
2327*5113495bSYour Name 			*fft_bin_size = 4;
2328*5113495bSYour Name 			break;
2329*5113495bSYour Name 		case SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE:
2330*5113495bSYour Name 			fft_bin_count >>= 1;
2331*5113495bSYour Name 			*fft_bin_size = 2;
2332*5113495bSYour Name 			/* Ideally we should be dividing fft bin length
2333*5113495bSYour Name 			 * by 2. Due to a HW bug, actual length is two
2334*5113495bSYour Name 			 * times the expected length.
2335*5113495bSYour Name 			 */
2336*5113495bSYour Name 			if (swar->packmode_fftbin_size_adj)
2337*5113495bSYour Name 				fft_bin_count >>= 1;
2338*5113495bSYour Name 			break;
2339*5113495bSYour Name 		case SPECTRAL_FFTBIN_SIZE_NO_WAR:
2340*5113495bSYour Name 			fallthrough;
2341*5113495bSYour Name 		default:
2342*5113495bSYour Name 			*fft_bin_size = 1;
2343*5113495bSYour Name 			/* No length adjustment */
2344*5113495bSYour Name 		}
2345*5113495bSYour Name 
2346*5113495bSYour Name 		if (rpt_mode == 2 && swar->inband_fftbin_size_adj)
2347*5113495bSYour Name 			fft_bin_count >>= 1;
2348*5113495bSYour Name 	}
2349*5113495bSYour Name 
2350*5113495bSYour Name 	return fft_bin_count;
2351*5113495bSYour Name }
2352*5113495bSYour Name 
2353*5113495bSYour Name #ifndef OPTIMIZED_SAMP_MESSAGE
2354*5113495bSYour Name /**
2355*5113495bSYour Name  * target_if_process_sfft_report_gen3() - Process Search FFT Report for gen3
2356*5113495bSYour Name  * @p_fft_report: Pointer to fft report
2357*5113495bSYour Name  * @p_sfft: Pointer to search fft report
2358*5113495bSYour Name  * @rparams: pointer to report params object
2359*5113495bSYour Name  *
2360*5113495bSYour Name  * Process Search FFT Report for gen3
2361*5113495bSYour Name  *
2362*5113495bSYour Name  * Return: Success/Failure
2363*5113495bSYour Name  */
2364*5113495bSYour Name static int
target_if_process_sfft_report_gen3(struct spectral_phyerr_fft_report_gen3 * p_fft_report,struct spectral_search_fft_info_gen3 * p_sfft,struct spectral_report_params * rparams)2365*5113495bSYour Name target_if_process_sfft_report_gen3(
2366*5113495bSYour Name 	struct spectral_phyerr_fft_report_gen3 *p_fft_report,
2367*5113495bSYour Name 	struct spectral_search_fft_info_gen3 *p_sfft,
2368*5113495bSYour Name 	struct spectral_report_params *rparams)
2369*5113495bSYour Name {
2370*5113495bSYour Name 	int32_t peak_sidx = 0;
2371*5113495bSYour Name 	int32_t peak_mag;
2372*5113495bSYour Name 
2373*5113495bSYour Name 	if (!p_fft_report || !p_sfft || !rparams) {
2374*5113495bSYour Name 		spectral_err("null params: p_fft_report %pK p_sfft %pK rparams %pK",
2375*5113495bSYour Name 			     p_fft_report, p_sfft, rparams);
2376*5113495bSYour Name 		return -EINVAL;
2377*5113495bSYour Name 	}
2378*5113495bSYour Name 
2379*5113495bSYour Name 	/*
2380*5113495bSYour Name 	 * For simplicity, everything is defined as uint32_t (except one).
2381*5113495bSYour Name 	 * Proper code will later use the right sizes.
2382*5113495bSYour Name 	 */
2383*5113495bSYour Name 	/*
2384*5113495bSYour Name 	 * For easy comparison between MDK team and OS team, the MDK script
2385*5113495bSYour Name 	 * variable names have been used
2386*5113495bSYour Name 	 */
2387*5113495bSYour Name 
2388*5113495bSYour Name 	/* Populate the Search FFT Info */
2389*5113495bSYour Name 	p_sfft->timestamp = p_fft_report->fft_timestamp;
2390*5113495bSYour Name 
2391*5113495bSYour Name 	p_sfft->fft_detector_id = get_bitfield(p_fft_report->hdr_a,
2392*5113495bSYour Name 					       2, 0);
2393*5113495bSYour Name 	p_sfft->fft_num = get_bitfield(p_fft_report->hdr_a, 3, 2);
2394*5113495bSYour Name 
2395*5113495bSYour Name 	switch (rparams->version) {
2396*5113495bSYour Name 	case SPECTRAL_REPORT_FORMAT_VERSION_1:
2397*5113495bSYour Name 		p_sfft->fft_radar_check = get_bitfield(p_fft_report->hdr_a,
2398*5113495bSYour Name 						       12, 5);
2399*5113495bSYour Name 		peak_sidx = get_bitfield(p_fft_report->hdr_a, 11, 17);
2400*5113495bSYour Name 		p_sfft->fft_chn_idx = get_bitfield(p_fft_report->hdr_a, 3, 28);
2401*5113495bSYour Name 		p_sfft->fft_base_pwr_db = get_bitfield(p_fft_report->hdr_b,
2402*5113495bSYour Name 						       9, 0);
2403*5113495bSYour Name 		p_sfft->fft_total_gain_db = get_bitfield(p_fft_report->hdr_b,
2404*5113495bSYour Name 							 8, 9);
2405*5113495bSYour Name 		break;
2406*5113495bSYour Name 	case SPECTRAL_REPORT_FORMAT_VERSION_2:
2407*5113495bSYour Name 		p_sfft->fft_radar_check = get_bitfield(p_fft_report->hdr_a,
2408*5113495bSYour Name 						       14, 5);
2409*5113495bSYour Name 		peak_sidx = get_bitfield(p_fft_report->hdr_a, 11, 19);
2410*5113495bSYour Name 		p_sfft->fft_chn_idx = get_bitfield(p_fft_report->hdr_b, 3, 0);
2411*5113495bSYour Name 		p_sfft->fft_base_pwr_db = get_bitfield(p_fft_report->hdr_b,
2412*5113495bSYour Name 						       9, 3);
2413*5113495bSYour Name 		p_sfft->fft_total_gain_db = get_bitfield(p_fft_report->hdr_b,
2414*5113495bSYour Name 							 8, 12);
2415*5113495bSYour Name 		break;
2416*5113495bSYour Name 	default:
2417*5113495bSYour Name 		spectral_err_rl("Invalid spectral report format: %d",
2418*5113495bSYour Name 				rparams->version);
2419*5113495bSYour Name 		return -EINVAL;
2420*5113495bSYour Name 	}
2421*5113495bSYour Name 
2422*5113495bSYour Name 	p_sfft->fft_peak_sidx = unsigned_to_signed(peak_sidx, 11);
2423*5113495bSYour Name 
2424*5113495bSYour Name 	p_sfft->fft_num_str_bins_ib = get_bitfield(p_fft_report->hdr_c,
2425*5113495bSYour Name 						   8, 0);
2426*5113495bSYour Name 	peak_mag = get_bitfield(p_fft_report->hdr_c, 10, 8);
2427*5113495bSYour Name 	p_sfft->fft_peak_mag = unsigned_to_signed(peak_mag, 10);
2428*5113495bSYour Name 	p_sfft->fft_avgpwr_db = get_bitfield(p_fft_report->hdr_c,
2429*5113495bSYour Name 					     7, 18);
2430*5113495bSYour Name 	p_sfft->fft_relpwr_db = get_bitfield(p_fft_report->hdr_c,
2431*5113495bSYour Name 					     7, 25);
2432*5113495bSYour Name 
2433*5113495bSYour Name 	return 0;
2434*5113495bSYour Name }
2435*5113495bSYour Name #endif
2436*5113495bSYour Name 
2437*5113495bSYour Name /**
2438*5113495bSYour Name  * target_if_dump_fft_report_gen3() - Dump FFT Report for gen3
2439*5113495bSYour Name  * @spectral: Pointer to Spectral object
2440*5113495bSYour Name  * @smode: Spectral scan mode
2441*5113495bSYour Name  * @p_fft_report: Pointer to fft report
2442*5113495bSYour Name  * @p_sfft: Pointer to search fft report
2443*5113495bSYour Name  *
2444*5113495bSYour Name  * Dump FFT Report for gen3
2445*5113495bSYour Name  *
2446*5113495bSYour Name  * Return: void
2447*5113495bSYour Name  */
2448*5113495bSYour Name static void
target_if_dump_fft_report_gen3(struct target_if_spectral * spectral,enum spectral_scan_mode smode,struct spectral_phyerr_fft_report_gen3 * p_fft_report,struct spectral_search_fft_info_gen3 * p_sfft)2449*5113495bSYour Name target_if_dump_fft_report_gen3(struct target_if_spectral *spectral,
2450*5113495bSYour Name 			enum spectral_scan_mode smode,
2451*5113495bSYour Name 			struct spectral_phyerr_fft_report_gen3 *p_fft_report,
2452*5113495bSYour Name 			struct spectral_search_fft_info_gen3 *p_sfft)
2453*5113495bSYour Name {
2454*5113495bSYour Name 	size_t fft_hdr_length;
2455*5113495bSYour Name 	size_t report_len;
2456*5113495bSYour Name 	size_t fft_bin_len;
2457*5113495bSYour Name 	size_t fft_bin_count;
2458*5113495bSYour Name 	size_t fft_bin_size;
2459*5113495bSYour Name 	size_t fft_bin_len_inband_tfer = 0;
2460*5113495bSYour Name 	uint8_t tag, signature;
2461*5113495bSYour Name 
2462*5113495bSYour Name 	if (!spectral) {
2463*5113495bSYour Name 		spectral_err_rl("spectral pointer is null.");
2464*5113495bSYour Name 		return;
2465*5113495bSYour Name 	}
2466*5113495bSYour Name 
2467*5113495bSYour Name 	/* There won't be FFT report/bins in report mode 0, so return */
2468*5113495bSYour Name 	if (!spectral->params[smode].ss_rpt_mode)
2469*5113495bSYour Name 		return;
2470*5113495bSYour Name 
2471*5113495bSYour Name 	fft_hdr_length = get_bitfield(
2472*5113495bSYour Name 				p_fft_report->fft_hdr_lts,
2473*5113495bSYour Name 				SPECTRAL_REPORT_LTS_HDR_LENGTH_SIZE_GEN3,
2474*5113495bSYour Name 				SPECTRAL_REPORT_LTS_HDR_LENGTH_POS_GEN3) * 4;
2475*5113495bSYour Name 
2476*5113495bSYour Name 	tag = get_bitfield(p_fft_report->fft_hdr_lts,
2477*5113495bSYour Name 			   SPECTRAL_REPORT_LTS_TAG_SIZE_GEN3,
2478*5113495bSYour Name 			   SPECTRAL_REPORT_LTS_TAG_POS_GEN3);
2479*5113495bSYour Name 
2480*5113495bSYour Name 	signature = get_bitfield(p_fft_report->fft_hdr_lts,
2481*5113495bSYour Name 				 SPECTRAL_REPORT_LTS_SIGNATURE_SIZE_GEN3,
2482*5113495bSYour Name 				 SPECTRAL_REPORT_LTS_SIGNATURE_POS_GEN3);
2483*5113495bSYour Name 
2484*5113495bSYour Name 	report_len = (fft_hdr_length + 8);
2485*5113495bSYour Name 	fft_bin_len = fft_hdr_length - spectral->rparams.fft_report_hdr_len;
2486*5113495bSYour Name 	fft_bin_count = target_if_spectral_get_bin_count_after_len_adj(
2487*5113495bSYour Name 			fft_bin_len,
2488*5113495bSYour Name 			spectral->params[smode].ss_rpt_mode,
2489*5113495bSYour Name 			&spectral->len_adj_swar, &fft_bin_size);
2490*5113495bSYour Name 
2491*5113495bSYour Name 	if ((spectral->params[smode].ss_rpt_mode == 2) &&
2492*5113495bSYour Name 	    spectral->len_adj_swar.inband_fftbin_size_adj)
2493*5113495bSYour Name 		fft_bin_len_inband_tfer = fft_bin_len >> 1;
2494*5113495bSYour Name 
2495*5113495bSYour Name 	spectral_debug("Spectral FFT Report");
2496*5113495bSYour Name 	spectral_debug("fft_timestamp = 0x%x", p_fft_report->fft_timestamp);
2497*5113495bSYour Name 	spectral_debug("fft_hdr_length = %zu(32 bit words)",
2498*5113495bSYour Name 		       fft_hdr_length >> 2);
2499*5113495bSYour Name 	spectral_debug("fft_hdr_tag = 0x%x", tag);
2500*5113495bSYour Name 	spectral_debug("fft_hdr_sig = 0x%x", signature);
2501*5113495bSYour Name 
2502*5113495bSYour Name 	spectral_debug("Length field in search fft report is %zu(0x%zx) bytes",
2503*5113495bSYour Name 		       fft_hdr_length, fft_hdr_length);
2504*5113495bSYour Name 	spectral_debug("Total length of search fft report is %zu(0x%zx) bytes",
2505*5113495bSYour Name 		       report_len, report_len);
2506*5113495bSYour Name 	spectral_debug("Target reported fftbins in report is %zu(0x%zx)",
2507*5113495bSYour Name 		       fft_bin_len, fft_bin_len);
2508*5113495bSYour Name 
2509*5113495bSYour Name 	if ((spectral->params[smode].ss_rpt_mode == 1) &&
2510*5113495bSYour Name 	    spectral->len_adj_swar.null_fftbin_adj)
2511*5113495bSYour Name 		spectral_debug("WAR: Considering number of FFT bins as 0");
2512*5113495bSYour Name 	else if ((spectral->params[smode].ss_rpt_mode == 2) &&
2513*5113495bSYour Name 		 spectral->len_adj_swar.inband_fftbin_size_adj) {
2514*5113495bSYour Name 		spectral_debug("FW fftbins actually transferred (in-band report mode) %zu(0x%zx)",
2515*5113495bSYour Name 			       fft_bin_len_inband_tfer,
2516*5113495bSYour Name 			       fft_bin_len_inband_tfer);
2517*5113495bSYour Name 	}
2518*5113495bSYour Name 
2519*5113495bSYour Name 	spectral_debug("Actual number of fftbins in report is %zu(0x%zx)",
2520*5113495bSYour Name 		       fft_bin_count, fft_bin_count);
2521*5113495bSYour Name 
2522*5113495bSYour Name 	spectral_debug("fft_detector_id = %u", p_sfft->fft_detector_id);
2523*5113495bSYour Name 	spectral_debug("fft_num = %u", p_sfft->fft_num);
2524*5113495bSYour Name 	spectral_debug("fft_radar_check = %u", p_sfft->fft_radar_check);
2525*5113495bSYour Name 	spectral_debug("fft_peak_sidx = %d",  p_sfft->fft_peak_sidx);
2526*5113495bSYour Name 	spectral_debug("fft_chn_idx = %u", p_sfft->fft_chn_idx);
2527*5113495bSYour Name 	spectral_debug("fft_base_pwr_db = %u", p_sfft->fft_base_pwr_db);
2528*5113495bSYour Name 	spectral_debug("fft_total_gain_db = %u", p_sfft->fft_total_gain_db);
2529*5113495bSYour Name 	spectral_debug("fft_num_str_bins_ib = %u", p_sfft->fft_num_str_bins_ib);
2530*5113495bSYour Name 	spectral_debug("fft_peak_mag = %d", p_sfft->fft_peak_mag);
2531*5113495bSYour Name 	spectral_debug("fft_avgpwr_db = %u", p_sfft->fft_avgpwr_db);
2532*5113495bSYour Name 	spectral_debug("fft_relpwr_db = %u", p_sfft->fft_relpwr_db);
2533*5113495bSYour Name 
2534*5113495bSYour Name 	if (fft_bin_count > 0) {
2535*5113495bSYour Name 		uint8_t *fft_bin_buf;
2536*5113495bSYour Name 		uint32_t bytes_copied;
2537*5113495bSYour Name 		QDF_STATUS status;
2538*5113495bSYour Name 
2539*5113495bSYour Name 		fft_bin_buf = qdf_mem_malloc(fft_bin_count);
2540*5113495bSYour Name 		if (!fft_bin_buf) {
2541*5113495bSYour Name 			spectral_err_rl("memory allocation failed");
2542*5113495bSYour Name 			return;
2543*5113495bSYour Name 		}
2544*5113495bSYour Name 
2545*5113495bSYour Name 		status = target_if_spectral_copy_fft_bins(
2546*5113495bSYour Name 				spectral, &p_fft_report->buf,
2547*5113495bSYour Name 				fft_bin_buf, fft_bin_count, &bytes_copied,
2548*5113495bSYour Name 				spectral->params[smode].ss_pwr_format);
2549*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
2550*5113495bSYour Name 			spectral_err_rl("Unable to populate FFT bins");
2551*5113495bSYour Name 			qdf_mem_free(fft_bin_buf);
2552*5113495bSYour Name 			return;
2553*5113495bSYour Name 		}
2554*5113495bSYour Name 
2555*5113495bSYour Name 		spectral_debug("FFT bin buffer size = %zu", fft_bin_count);
2556*5113495bSYour Name 		spectral_debug("FFT bins:");
2557*5113495bSYour Name 		target_if_spectral_hexdump(fft_bin_buf, fft_bin_count);
2558*5113495bSYour Name 		qdf_mem_free(fft_bin_buf);
2559*5113495bSYour Name 	}
2560*5113495bSYour Name }
2561*5113495bSYour Name #endif
2562*5113495bSYour Name 
2563*5113495bSYour Name #ifdef OPTIMIZED_SAMP_MESSAGE
2564*5113495bSYour Name QDF_STATUS
target_if_160mhz_delivery_state_change(struct target_if_spectral * spectral,enum spectral_scan_mode smode,uint8_t detector_id)2565*5113495bSYour Name target_if_160mhz_delivery_state_change(struct target_if_spectral *spectral,
2566*5113495bSYour Name 				       enum spectral_scan_mode smode,
2567*5113495bSYour Name 				       uint8_t detector_id) {
2568*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
2569*5113495bSYour Name 
2570*5113495bSYour Name 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
2571*5113495bSYour Name 		spectral_err_rl("Invalid Spectral mode %d", smode);
2572*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
2573*5113495bSYour Name 	}
2574*5113495bSYour Name 
2575*5113495bSYour Name 	if (!is_ch_width_160_or_80p80(spectral->report_info[smode].sscan_bw)) {
2576*5113495bSYour Name 		spectral_err_rl("Scan BW %d is not 160/80p80 for mode %d",
2577*5113495bSYour Name 				spectral->report_info[smode].sscan_bw, smode);
2578*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
2579*5113495bSYour Name 	}
2580*5113495bSYour Name 
2581*5113495bSYour Name 	switch (spectral->state_160mhz_delivery[smode]) {
2582*5113495bSYour Name 	case SPECTRAL_REPORT_WAIT_PRIMARY80:
2583*5113495bSYour Name 		if (detector_id == SPECTRAL_DETECTOR_ID_0)
2584*5113495bSYour Name 			spectral->state_160mhz_delivery[smode] =
2585*5113495bSYour Name 				SPECTRAL_REPORT_WAIT_SECONDARY80;
2586*5113495bSYour Name 		else {
2587*5113495bSYour Name 			status = QDF_STATUS_E_FAILURE;
2588*5113495bSYour Name 			spectral->diag_stats.spectral_vhtseg1id_mismatch++;
2589*5113495bSYour Name 		}
2590*5113495bSYour Name 		break;
2591*5113495bSYour Name 
2592*5113495bSYour Name 	case SPECTRAL_REPORT_WAIT_SECONDARY80:
2593*5113495bSYour Name 		if (detector_id == SPECTRAL_DETECTOR_ID_1)
2594*5113495bSYour Name 			spectral->state_160mhz_delivery[smode] =
2595*5113495bSYour Name 				SPECTRAL_REPORT_WAIT_PRIMARY80;
2596*5113495bSYour Name 		else {
2597*5113495bSYour Name 			spectral->state_160mhz_delivery[smode] =
2598*5113495bSYour Name 				SPECTRAL_REPORT_WAIT_PRIMARY80;
2599*5113495bSYour Name 			status = QDF_STATUS_E_FAILURE;
2600*5113495bSYour Name 			spectral->diag_stats.spectral_vhtseg2id_mismatch++;
2601*5113495bSYour Name 		}
2602*5113495bSYour Name 		break;
2603*5113495bSYour Name 
2604*5113495bSYour Name 	default:
2605*5113495bSYour Name 		break;
2606*5113495bSYour Name 	}
2607*5113495bSYour Name 
2608*5113495bSYour Name 	return status;
2609*5113495bSYour Name }
2610*5113495bSYour Name #else
2611*5113495bSYour Name QDF_STATUS
target_if_160mhz_delivery_state_change(struct target_if_spectral * spectral,enum spectral_scan_mode smode,uint8_t detector_id)2612*5113495bSYour Name target_if_160mhz_delivery_state_change(struct target_if_spectral *spectral,
2613*5113495bSYour Name 				       enum spectral_scan_mode smode,
2614*5113495bSYour Name 				       uint8_t detector_id) {
2615*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
2616*5113495bSYour Name 
2617*5113495bSYour Name 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
2618*5113495bSYour Name 		spectral_err_rl("Invalid Spectral mode %d", smode);
2619*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
2620*5113495bSYour Name 	}
2621*5113495bSYour Name 
2622*5113495bSYour Name 	if (!is_ch_width_160_or_80p80(spectral->ch_width[smode])) {
2623*5113495bSYour Name 		spectral_err_rl("Scan BW %d is not 160/80p80 for mode %d",
2624*5113495bSYour Name 				spectral->ch_width[smode], smode);
2625*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
2626*5113495bSYour Name 	}
2627*5113495bSYour Name 
2628*5113495bSYour Name 	switch (spectral->state_160mhz_delivery[smode]) {
2629*5113495bSYour Name 	case SPECTRAL_REPORT_WAIT_PRIMARY80:
2630*5113495bSYour Name 		if (detector_id == SPECTRAL_DETECTOR_ID_0)
2631*5113495bSYour Name 			spectral->state_160mhz_delivery[smode] =
2632*5113495bSYour Name 				SPECTRAL_REPORT_RX_PRIMARY80;
2633*5113495bSYour Name 		else {
2634*5113495bSYour Name 			status = QDF_STATUS_E_FAILURE;
2635*5113495bSYour Name 			spectral->diag_stats.spectral_vhtseg1id_mismatch++;
2636*5113495bSYour Name 		}
2637*5113495bSYour Name 		break;
2638*5113495bSYour Name 
2639*5113495bSYour Name 	case SPECTRAL_REPORT_WAIT_SECONDARY80:
2640*5113495bSYour Name 		if (detector_id == SPECTRAL_DETECTOR_ID_1)
2641*5113495bSYour Name 			spectral->state_160mhz_delivery[smode] =
2642*5113495bSYour Name 				SPECTRAL_REPORT_RX_SECONDARY80;
2643*5113495bSYour Name 		else {
2644*5113495bSYour Name 			spectral->state_160mhz_delivery[smode] =
2645*5113495bSYour Name 				SPECTRAL_REPORT_WAIT_PRIMARY80;
2646*5113495bSYour Name 			status = QDF_STATUS_E_FAILURE;
2647*5113495bSYour Name 			spectral->diag_stats.spectral_vhtseg2id_mismatch++;
2648*5113495bSYour Name 		}
2649*5113495bSYour Name 		break;
2650*5113495bSYour Name 
2651*5113495bSYour Name 	case SPECTRAL_REPORT_RX_SECONDARY80:
2652*5113495bSYour Name 		/* We don't care about detector id in this state. */
2653*5113495bSYour Name 		reset_160mhz_delivery_state_machine(spectral, smode);
2654*5113495bSYour Name 		break;
2655*5113495bSYour Name 
2656*5113495bSYour Name 	case SPECTRAL_REPORT_RX_PRIMARY80:
2657*5113495bSYour Name 		/* We don't care about detector id in this state */
2658*5113495bSYour Name 		spectral->state_160mhz_delivery[smode] =
2659*5113495bSYour Name 				SPECTRAL_REPORT_WAIT_SECONDARY80;
2660*5113495bSYour Name 		break;
2661*5113495bSYour Name 
2662*5113495bSYour Name 	default:
2663*5113495bSYour Name 		break;
2664*5113495bSYour Name 	}
2665*5113495bSYour Name 
2666*5113495bSYour Name 	return status;
2667*5113495bSYour Name }
2668*5113495bSYour Name #endif /* OPTIMIZED_SAMP_MESSAGE */
2669*5113495bSYour Name 
2670*5113495bSYour Name #ifdef DIRECT_BUF_RX_ENABLE
2671*5113495bSYour Name /**
2672*5113495bSYour Name  * target_if_get_detector_id_sscan_summary_report_gen3() - Get Spectral detector
2673*5113495bSYour Name  * ID from Spectral summary report
2674*5113495bSYour Name  * @data: Pointer to Spectral summary report
2675*5113495bSYour Name  * @detector_id: Pointer to detector id
2676*5113495bSYour Name  *
2677*5113495bSYour Name  * Return: QDF_STATUS
2678*5113495bSYour Name  */
2679*5113495bSYour Name static QDF_STATUS
target_if_get_detector_id_sscan_summary_report_gen3(uint8_t * data,uint8_t * detector_id)2680*5113495bSYour Name target_if_get_detector_id_sscan_summary_report_gen3(uint8_t *data,
2681*5113495bSYour Name 						    uint8_t *detector_id)
2682*5113495bSYour Name {
2683*5113495bSYour Name 	struct spectral_sscan_summary_report_gen3 *psscan_summary_report;
2684*5113495bSYour Name 
2685*5113495bSYour Name 	if (!data) {
2686*5113495bSYour Name 		spectral_err("Argument(data) is null.");
2687*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
2688*5113495bSYour Name 	}
2689*5113495bSYour Name 
2690*5113495bSYour Name 	psscan_summary_report =
2691*5113495bSYour Name 		(struct spectral_sscan_summary_report_gen3 *)data;
2692*5113495bSYour Name 
2693*5113495bSYour Name 	*detector_id = get_bitfield(
2694*5113495bSYour Name 			psscan_summary_report->hdr_a,
2695*5113495bSYour Name 			SSCAN_SUMMARY_REPORT_HDR_A_DETECTOR_ID_SIZE_GEN3,
2696*5113495bSYour Name 			SSCAN_SUMMARY_REPORT_HDR_A_DETECTOR_ID_POS_GEN3);
2697*5113495bSYour Name 
2698*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
2699*5113495bSYour Name }
2700*5113495bSYour Name 
2701*5113495bSYour Name #ifndef OPTIMIZED_SAMP_MESSAGE
2702*5113495bSYour Name /**
2703*5113495bSYour Name  * target_if_consume_sscan_summary_report_gen3() - Consume Spectral summary
2704*5113495bSYour Name  * report
2705*5113495bSYour Name  * @data: Pointer to Spectral summary report
2706*5113495bSYour Name  * @fields: Pointer to structure to be populated with extracted fields
2707*5113495bSYour Name  * @rparams: Pointer to structure with Spectral report params
2708*5113495bSYour Name  *
2709*5113495bSYour Name  * Consume Spectral summary report for gen3
2710*5113495bSYour Name  *
2711*5113495bSYour Name  * Return: void
2712*5113495bSYour Name  */
2713*5113495bSYour Name static void
target_if_consume_sscan_summary_report_gen3(uint8_t * data,struct sscan_report_fields_gen3 * fields,struct spectral_report_params * rparams)2714*5113495bSYour Name target_if_consume_sscan_summary_report_gen3(
2715*5113495bSYour Name 				uint8_t *data,
2716*5113495bSYour Name 				struct sscan_report_fields_gen3 *fields,
2717*5113495bSYour Name 				struct spectral_report_params *rparams) {
2718*5113495bSYour Name 	struct spectral_sscan_summary_report_gen3 *psscan_summary_report;
2719*5113495bSYour Name 
2720*5113495bSYour Name 	if (!data || !fields || !rparams) {
2721*5113495bSYour Name 		spectral_err("null arguments: data %pK, fields %pK, rparams %pK.",
2722*5113495bSYour Name 			     data, fields, rparams);
2723*5113495bSYour Name 		return;
2724*5113495bSYour Name 	}
2725*5113495bSYour Name 
2726*5113495bSYour Name 	psscan_summary_report =
2727*5113495bSYour Name 		(struct spectral_sscan_summary_report_gen3 *)data;
2728*5113495bSYour Name 
2729*5113495bSYour Name 	fields->sscan_agc_total_gain = get_bitfield(
2730*5113495bSYour Name 			psscan_summary_report->hdr_a,
2731*5113495bSYour Name 			SSCAN_SUMMARY_REPORT_HDR_A_AGC_TOTAL_GAIN_SIZE_GEN3,
2732*5113495bSYour Name 			SSCAN_SUMMARY_REPORT_HDR_A_AGC_TOTAL_GAIN_POS_GEN3);
2733*5113495bSYour Name 	fields->inband_pwr_db = get_bitfield(
2734*5113495bSYour Name 			psscan_summary_report->hdr_a,
2735*5113495bSYour Name 			SSCAN_SUMMARY_REPORT_HDR_A_INBAND_PWR_DB_SIZE_GEN3,
2736*5113495bSYour Name 			SSCAN_SUMMARY_REPORT_HDR_A_INBAND_PWR_DB_POS_GEN3);
2737*5113495bSYour Name 	fields->sscan_pri80 = get_bitfield(
2738*5113495bSYour Name 			psscan_summary_report->hdr_a,
2739*5113495bSYour Name 			SSCAN_SUMMARY_REPORT_HDR_A_PRI80_SIZE_GEN3,
2740*5113495bSYour Name 			SSCAN_SUMMARY_REPORT_HDR_A_PRI80_POS_GEN3);
2741*5113495bSYour Name 
2742*5113495bSYour Name 	switch (rparams->version) {
2743*5113495bSYour Name 	case SPECTRAL_REPORT_FORMAT_VERSION_1:
2744*5113495bSYour Name 		fields->sscan_gainchange = get_bitfield(
2745*5113495bSYour Name 			psscan_summary_report->hdr_b,
2746*5113495bSYour Name 			SSCAN_SUMMARY_REPORT_HDR_B_GAINCHANGE_SIZE_GEN3_V1,
2747*5113495bSYour Name 			SSCAN_SUMMARY_REPORT_HDR_B_GAINCHANGE_POS_GEN3_V1);
2748*5113495bSYour Name 		break;
2749*5113495bSYour Name 	case SPECTRAL_REPORT_FORMAT_VERSION_2:
2750*5113495bSYour Name 		fields->sscan_gainchange = get_bitfield(
2751*5113495bSYour Name 			psscan_summary_report->hdr_c,
2752*5113495bSYour Name 			SSCAN_SUMMARY_REPORT_HDR_C_GAINCHANGE_SIZE_GEN3_V2,
2753*5113495bSYour Name 			SSCAN_SUMMARY_REPORT_HDR_C_GAINCHANGE_POS_GEN3_V2);
2754*5113495bSYour Name 		break;
2755*5113495bSYour Name 	default:
2756*5113495bSYour Name 		spectral_err("Invalid spectral report format version: %d.",
2757*5113495bSYour Name 			     rparams->version);
2758*5113495bSYour Name 		return;
2759*5113495bSYour Name 	}
2760*5113495bSYour Name }
2761*5113495bSYour Name #endif
2762*5113495bSYour Name 
2763*5113495bSYour Name /**
2764*5113495bSYour Name  * target_if_verify_sig_and_tag_gen3() - Verify tag and signature
2765*5113495bSYour Name  *                                       of spectral report
2766*5113495bSYour Name  * @spectral: Pointer to spectral object
2767*5113495bSYour Name  * @data: Pointer to spectral summary report
2768*5113495bSYour Name  * @exp_tag: iexpected tag value
2769*5113495bSYour Name  *
2770*5113495bSYour Name  * Process fft report for gen3
2771*5113495bSYour Name  *
2772*5113495bSYour Name  * Return: SUCCESS/FAILURE
2773*5113495bSYour Name  */
2774*5113495bSYour Name static int
target_if_verify_sig_and_tag_gen3(struct target_if_spectral * spectral,uint8_t * data,uint8_t exp_tag)2775*5113495bSYour Name target_if_verify_sig_and_tag_gen3(struct target_if_spectral *spectral,
2776*5113495bSYour Name 				  uint8_t *data, uint8_t exp_tag)
2777*5113495bSYour Name {
2778*5113495bSYour Name 	uint8_t tag = 0;
2779*5113495bSYour Name 	uint8_t signature = 0;
2780*5113495bSYour Name 	uint32_t lts;
2781*5113495bSYour Name 
2782*5113495bSYour Name 	lts = *((uint32_t *)(data + SPECTRAL_PHYERR_HDR_LTS_POS));
2783*5113495bSYour Name 	/* Peek into the data to figure out whether
2784*5113495bSYour Name 	 *      1) Signature matches the expected value
2785*5113495bSYour Name 	 *      2) What is inside the package (TAG ID is used for finding this)
2786*5113495bSYour Name 	 */
2787*5113495bSYour Name 	tag = get_bitfield(lts,
2788*5113495bSYour Name 			   SPECTRAL_REPORT_LTS_TAG_SIZE_GEN3,
2789*5113495bSYour Name 			   SPECTRAL_REPORT_LTS_TAG_POS_GEN3);
2790*5113495bSYour Name 
2791*5113495bSYour Name 	signature = get_bitfield(lts,
2792*5113495bSYour Name 				 SPECTRAL_REPORT_LTS_SIGNATURE_SIZE_GEN3,
2793*5113495bSYour Name 				 SPECTRAL_REPORT_LTS_SIGNATURE_POS_GEN3);
2794*5113495bSYour Name 
2795*5113495bSYour Name 
2796*5113495bSYour Name 	if (signature != SPECTRAL_PHYERR_SIGNATURE_GEN3) {
2797*5113495bSYour Name 		spectral->diag_stats.spectral_mismatch++;
2798*5113495bSYour Name 		return -EINVAL;
2799*5113495bSYour Name 	}
2800*5113495bSYour Name 
2801*5113495bSYour Name 	if (tag != exp_tag) {
2802*5113495bSYour Name 		spectral->diag_stats.spectral_mismatch++;
2803*5113495bSYour Name 		return -EINVAL;
2804*5113495bSYour Name 	}
2805*5113495bSYour Name 
2806*5113495bSYour Name 	return 0;
2807*5113495bSYour Name }
2808*5113495bSYour Name 
2809*5113495bSYour Name static uint8_t
target_if_spectral_get_lowest_chn_idx(uint8_t chainmask)2810*5113495bSYour Name target_if_spectral_get_lowest_chn_idx(uint8_t chainmask)
2811*5113495bSYour Name {
2812*5113495bSYour Name 	uint8_t idx;
2813*5113495bSYour Name 
2814*5113495bSYour Name 	for (idx = 0; idx < DBR_MAX_CHAINS; idx++) {
2815*5113495bSYour Name 		if (chainmask & 0x1)
2816*5113495bSYour Name 			break;
2817*5113495bSYour Name 		chainmask >>= 1;
2818*5113495bSYour Name 	}
2819*5113495bSYour Name 	return idx;
2820*5113495bSYour Name }
2821*5113495bSYour Name 
2822*5113495bSYour Name #ifdef DIRECT_BUF_RX_DEBUG
target_if_spectral_check_buffer_poisoning(struct target_if_spectral * spectral,struct spectral_report * report,int num_fft_bins,enum spectral_scan_mode smode)2823*5113495bSYour Name static void target_if_spectral_check_buffer_poisoning(
2824*5113495bSYour Name 	struct target_if_spectral *spectral,
2825*5113495bSYour Name 	struct spectral_report *report,
2826*5113495bSYour Name 	int num_fft_bins, enum spectral_scan_mode smode)
2827*5113495bSYour Name {
2828*5113495bSYour Name 	uint32_t *data;
2829*5113495bSYour Name 	size_t len;
2830*5113495bSYour Name 	size_t words_to_check =
2831*5113495bSYour Name 		sizeof(struct spectral_sscan_summary_report_gen3) >> 2;
2832*5113495bSYour Name 	bool poisoned_words_found = false;
2833*5113495bSYour Name 
2834*5113495bSYour Name 	if (!spectral) {
2835*5113495bSYour Name 		spectral_err_rl("Spectral LMAC object is null");
2836*5113495bSYour Name 		return;
2837*5113495bSYour Name 	}
2838*5113495bSYour Name 
2839*5113495bSYour Name 	if (!spectral->dbr_buff_debug)
2840*5113495bSYour Name 		return;
2841*5113495bSYour Name 
2842*5113495bSYour Name 	if (!report) {
2843*5113495bSYour Name 		spectral_err_rl("Spectral report is null");
2844*5113495bSYour Name 		return;
2845*5113495bSYour Name 	}
2846*5113495bSYour Name 
2847*5113495bSYour Name 	/* Add search FFT report */
2848*5113495bSYour Name 	if (spectral->params[smode].ss_rpt_mode > 0)
2849*5113495bSYour Name 		words_to_check +=
2850*5113495bSYour Name 			sizeof(struct spectral_phyerr_fft_report_gen3) >> 2;
2851*5113495bSYour Name 
2852*5113495bSYour Name 	/* Now add the number of FFT bins */
2853*5113495bSYour Name 	if (spectral->params[smode].ss_rpt_mode > 1) {
2854*5113495bSYour Name 		/* Caller should take care to pass correct number of FFT bins */
2855*5113495bSYour Name 		if (spectral->len_adj_swar.fftbin_size_war ==
2856*5113495bSYour Name 				SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE)
2857*5113495bSYour Name 			words_to_check += num_fft_bins;
2858*5113495bSYour Name 		else if (spectral->len_adj_swar.fftbin_size_war ==
2859*5113495bSYour Name 				SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE)
2860*5113495bSYour Name 			words_to_check += (num_fft_bins >> 1);
2861*5113495bSYour Name 	}
2862*5113495bSYour Name 
2863*5113495bSYour Name 	data = (uint32_t *)report->data;
2864*5113495bSYour Name 	for (len = 0; len < words_to_check; ++len) {
2865*5113495bSYour Name 		if (*data == MEM_POISON_SIGNATURE) {
2866*5113495bSYour Name 			spectral_err("Pattern(%x) found in Spectral search FFT report at position %zu in the buffer %pK",
2867*5113495bSYour Name 				     MEM_POISON_SIGNATURE,
2868*5113495bSYour Name 				     (len << 2), report->data);
2869*5113495bSYour Name 			poisoned_words_found = true;
2870*5113495bSYour Name 			break;
2871*5113495bSYour Name 		}
2872*5113495bSYour Name 		++data;
2873*5113495bSYour Name 	}
2874*5113495bSYour Name 
2875*5113495bSYour Name 	/* Crash the FW even if one word is poisoned */
2876*5113495bSYour Name 	if (poisoned_words_found) {
2877*5113495bSYour Name 		spectral_err("Pattern(%x) found in Spectral report, Hex dump of the sfft follows",
2878*5113495bSYour Name 			     MEM_POISON_SIGNATURE);
2879*5113495bSYour Name 		target_if_spectral_hexdump((unsigned char *)report->data,
2880*5113495bSYour Name 					   words_to_check << 2);
2881*5113495bSYour Name 		spectral_err("Asserting the FW");
2882*5113495bSYour Name 		target_if_spectral_fw_hang(spectral);
2883*5113495bSYour Name 	}
2884*5113495bSYour Name }
2885*5113495bSYour Name 
2886*5113495bSYour Name #ifdef OPTIMIZED_SAMP_MESSAGE
target_if_spectral_verify_ts(struct target_if_spectral * spectral,uint8_t * buf,uint32_t current_ts,uint8_t detector_id)2887*5113495bSYour Name static void target_if_spectral_verify_ts(struct target_if_spectral *spectral,
2888*5113495bSYour Name 					 uint8_t *buf, uint32_t current_ts,
2889*5113495bSYour Name 					 uint8_t detector_id)
2890*5113495bSYour Name {
2891*5113495bSYour Name 	if (!spectral) {
2892*5113495bSYour Name 		spectral_err_rl("Spectral LMAC object is null");
2893*5113495bSYour Name 		return;
2894*5113495bSYour Name 	}
2895*5113495bSYour Name 	if (detector_id >= MAX_DETECTORS_PER_PDEV) {
2896*5113495bSYour Name 		spectral_err_rl("Spectral detector_id %d exceeds range",
2897*5113495bSYour Name 				detector_id);
2898*5113495bSYour Name 		return;
2899*5113495bSYour Name 	}
2900*5113495bSYour Name 
2901*5113495bSYour Name 	if (!spectral->dbr_buff_debug)
2902*5113495bSYour Name 		return;
2903*5113495bSYour Name 
2904*5113495bSYour Name 	if (spectral->prev_tstamp[detector_id]) {
2905*5113495bSYour Name 		if (current_ts == spectral->prev_tstamp[detector_id]) {
2906*5113495bSYour Name 			spectral_err("Spectral timestamp(%u) in the current buffer(%pK) is equal to the previous timestamp, same report DMAed twice? Asserting the FW",
2907*5113495bSYour Name 				     current_ts, buf);
2908*5113495bSYour Name 			target_if_spectral_fw_hang(spectral);
2909*5113495bSYour Name 		}
2910*5113495bSYour Name 	}
2911*5113495bSYour Name 	spectral->prev_tstamp[detector_id] = current_ts;
2912*5113495bSYour Name }
2913*5113495bSYour Name #else
target_if_spectral_verify_ts(struct target_if_spectral * spectral,uint8_t * buf,uint32_t current_ts)2914*5113495bSYour Name static void target_if_spectral_verify_ts(struct target_if_spectral *spectral,
2915*5113495bSYour Name 					 uint8_t *buf, uint32_t current_ts)
2916*5113495bSYour Name {
2917*5113495bSYour Name 	if (!spectral) {
2918*5113495bSYour Name 		spectral_err_rl("Spectral LMAC object is null");
2919*5113495bSYour Name 		return;
2920*5113495bSYour Name 	}
2921*5113495bSYour Name 
2922*5113495bSYour Name 	if (!spectral->dbr_buff_debug)
2923*5113495bSYour Name 		return;
2924*5113495bSYour Name 
2925*5113495bSYour Name 	if (spectral->prev_tstamp) {
2926*5113495bSYour Name 		if (current_ts == spectral->prev_tstamp) {
2927*5113495bSYour Name 			spectral_err("Spectral timestamp(%u) in the current buffer(%pK) is equal to the previous timestamp, same report DMAed twice? Asserting the FW",
2928*5113495bSYour Name 				     current_ts, buf);
2929*5113495bSYour Name 			target_if_spectral_fw_hang(spectral);
2930*5113495bSYour Name 		}
2931*5113495bSYour Name 	}
2932*5113495bSYour Name 	spectral->prev_tstamp = current_ts;
2933*5113495bSYour Name }
2934*5113495bSYour Name #endif /* OPTIMIZED_SAMP_MESSAGE */
2935*5113495bSYour Name #else
target_if_spectral_check_buffer_poisoning(struct target_if_spectral * spectral,struct spectral_report * report,int num_fft_bins,enum spectral_scan_mode smode)2936*5113495bSYour Name static void target_if_spectral_check_buffer_poisoning(
2937*5113495bSYour Name 	struct target_if_spectral *spectral,
2938*5113495bSYour Name 	struct spectral_report *report,
2939*5113495bSYour Name 	int num_fft_bins, enum spectral_scan_mode smode)
2940*5113495bSYour Name {
2941*5113495bSYour Name }
2942*5113495bSYour Name 
2943*5113495bSYour Name #ifdef OPTIMIZED_SAMP_MESSAGE
target_if_spectral_verify_ts(struct target_if_spectral * spectral,uint8_t * buf,uint32_t current_ts,uint8_t detector_id)2944*5113495bSYour Name static void target_if_spectral_verify_ts(struct target_if_spectral *spectral,
2945*5113495bSYour Name 					 uint8_t *buf, uint32_t current_ts,
2946*5113495bSYour Name 					 uint8_t detector_id)
2947*5113495bSYour Name {
2948*5113495bSYour Name }
2949*5113495bSYour Name #else
target_if_spectral_verify_ts(struct target_if_spectral * spectral,uint8_t * buf,uint32_t current_ts)2950*5113495bSYour Name static void target_if_spectral_verify_ts(struct target_if_spectral *spectral,
2951*5113495bSYour Name 					 uint8_t *buf, uint32_t current_ts)
2952*5113495bSYour Name {
2953*5113495bSYour Name }
2954*5113495bSYour Name #endif /* OPTIMIZED_SAMP_MESSAGE */
2955*5113495bSYour Name #endif
2956*5113495bSYour Name 
2957*5113495bSYour Name /**
2958*5113495bSYour Name  * target_if_spectral_get_adjusted_timestamp() - Adjust Spectral time
2959*5113495bSYour Name  * stamp to account for reset in time stamp due to target reset
2960*5113495bSYour Name  * @twar: Spectral time stamp WAR related information
2961*5113495bSYour Name  * @raw_timestamp: Spectral time stamp reported by target
2962*5113495bSYour Name  * @reset_delay: Reset delay at target
2963*5113495bSYour Name  * @smode: Spectral scan mode
2964*5113495bSYour Name  * @tstamp: Pointer to adjusted timestamp
2965*5113495bSYour Name  *
2966*5113495bSYour Name  * Correct time stamp to account for reset in time stamp due to target reset
2967*5113495bSYour Name  *
2968*5113495bSYour Name  * Return: QDF_STATUS
2969*5113495bSYour Name  */
2970*5113495bSYour Name static QDF_STATUS
target_if_spectral_get_adjusted_timestamp(struct spectral_timestamp_war * twar,uint32_t raw_timestamp,uint32_t reset_delay,enum spectral_scan_mode smode,uint32_t * tstamp)2971*5113495bSYour Name target_if_spectral_get_adjusted_timestamp(struct spectral_timestamp_war *twar,
2972*5113495bSYour Name 					  uint32_t raw_timestamp,
2973*5113495bSYour Name 					  uint32_t reset_delay,
2974*5113495bSYour Name 					  enum spectral_scan_mode smode,
2975*5113495bSYour Name 					  uint32_t *tstamp)
2976*5113495bSYour Name {
2977*5113495bSYour Name 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
2978*5113495bSYour Name 		spectral_err("Invalid spectral scan mode: %d", smode);
2979*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
2980*5113495bSYour Name 	}
2981*5113495bSYour Name 
2982*5113495bSYour Name 	if (reset_delay) {
2983*5113495bSYour Name 		enum spectral_scan_mode m =
2984*5113495bSYour Name 					SPECTRAL_SCAN_MODE_NORMAL;
2985*5113495bSYour Name 
2986*5113495bSYour Name 		/* Adjust the offset for all the Spectral modes.
2987*5113495bSYour Name 		 * Target will be sending the non zero reset delay for
2988*5113495bSYour Name 		 * the first Spectral report after reset. This delay is
2989*5113495bSYour Name 		 * common for all the Spectral modes.
2990*5113495bSYour Name 		 */
2991*5113495bSYour Name 		for (; m < SPECTRAL_SCAN_MODE_MAX; m++)
2992*5113495bSYour Name 			twar->timestamp_war_offset[m] += (reset_delay +
2993*5113495bSYour Name 					twar->last_fft_timestamp[m]);
2994*5113495bSYour Name 		twar->target_reset_count++;
2995*5113495bSYour Name 	}
2996*5113495bSYour Name 	twar->last_fft_timestamp[smode] = raw_timestamp;
2997*5113495bSYour Name 
2998*5113495bSYour Name 	*tstamp = raw_timestamp + twar->timestamp_war_offset[smode];
2999*5113495bSYour Name 
3000*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
3001*5113495bSYour Name }
3002*5113495bSYour Name 
3003*5113495bSYour Name #ifdef BIG_ENDIAN_HOST
target_if_byte_swap_spectral_headers_gen3(struct target_if_spectral * spectral,void * data)3004*5113495bSYour Name QDF_STATUS target_if_byte_swap_spectral_headers_gen3(
3005*5113495bSYour Name 	 struct target_if_spectral *spectral,
3006*5113495bSYour Name 	 void *data)
3007*5113495bSYour Name {
3008*5113495bSYour Name 	int i;
3009*5113495bSYour Name 	uint32_t *ptr32;
3010*5113495bSYour Name 	size_t words32;
3011*5113495bSYour Name 
3012*5113495bSYour Name 	if (!data || !spectral) {
3013*5113495bSYour Name 		spectral_err_rl("null params: data %pK, spectral %pK.",
3014*5113495bSYour Name 				data, spectral);
3015*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
3016*5113495bSYour Name 	}
3017*5113495bSYour Name 
3018*5113495bSYour Name 	ptr32 = (uint32_t *)data;
3019*5113495bSYour Name 
3020*5113495bSYour Name 	/* Summary Report */
3021*5113495bSYour Name 	words32 = sizeof(struct spectral_sscan_summary_report_gen3) >> 2;
3022*5113495bSYour Name 	for (i = 0; i < words32; ++i) {
3023*5113495bSYour Name 		*ptr32 = qdf_le32_to_cpu(*ptr32);
3024*5113495bSYour Name 		++ptr32;
3025*5113495bSYour Name 	}
3026*5113495bSYour Name 
3027*5113495bSYour Name 	/* No need to swap the padding bytes */
3028*5113495bSYour Name 	ptr32 += (spectral->rparams.ssummary_padding_bytes >> 2);
3029*5113495bSYour Name 
3030*5113495bSYour Name 	/* Search FFT Report */
3031*5113495bSYour Name 	words32 = sizeof(struct spectral_phyerr_fft_report_gen3) >> 2;
3032*5113495bSYour Name 	for (i = 0; i < words32; ++i) {
3033*5113495bSYour Name 		*ptr32 = qdf_le32_to_cpu(*ptr32);
3034*5113495bSYour Name 		++ptr32;
3035*5113495bSYour Name 	}
3036*5113495bSYour Name 
3037*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
3038*5113495bSYour Name }
3039*5113495bSYour Name 
target_if_byte_swap_spectral_fft_bins_gen3(const struct spectral_report_params * rparams,void * bin_pwr_data,size_t num_fftbins)3040*5113495bSYour Name QDF_STATUS target_if_byte_swap_spectral_fft_bins_gen3(
3041*5113495bSYour Name 	const struct spectral_report_params *rparams,
3042*5113495bSYour Name 	void *bin_pwr_data, size_t num_fftbins)
3043*5113495bSYour Name {
3044*5113495bSYour Name 	uint16_t dword_idx, num_dwords;
3045*5113495bSYour Name 	uint8_t num_bins_per_dword;
3046*5113495bSYour Name 	uint32_t *dword_ptr;
3047*5113495bSYour Name 
3048*5113495bSYour Name 	if (!bin_pwr_data || !rparams) {
3049*5113495bSYour Name 		spectral_err_rl("null params, bin_pwr_data %pK, rparams %pK.",
3050*5113495bSYour Name 				bin_pwr_data, rparams);
3051*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
3052*5113495bSYour Name 	}
3053*5113495bSYour Name 
3054*5113495bSYour Name 	num_bins_per_dword = SPECTRAL_DWORD_SIZE / rparams->hw_fft_bin_width;
3055*5113495bSYour Name 	num_dwords = num_fftbins / num_bins_per_dword;
3056*5113495bSYour Name 	dword_ptr = (uint32_t *)bin_pwr_data;
3057*5113495bSYour Name 
3058*5113495bSYour Name 	for (dword_idx = 0; dword_idx < num_dwords; dword_idx++) {
3059*5113495bSYour Name 		/* Read a DWORD, byteswap it, and copy it back */
3060*5113495bSYour Name 		*dword_ptr = qdf_le32_to_cpu(*dword_ptr);
3061*5113495bSYour Name 		++dword_ptr;
3062*5113495bSYour Name 	}
3063*5113495bSYour Name 
3064*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
3065*5113495bSYour Name }
3066*5113495bSYour Name #endif /* BIG_ENDIAN_HOST */
3067*5113495bSYour Name 
3068*5113495bSYour Name #ifdef OPTIMIZED_SAMP_MESSAGE
3069*5113495bSYour Name /**
3070*5113495bSYour Name  * target_if_consume_sscan_summary_report_gen3() - Consume Spectral summary
3071*5113495bSYour Name  * report
3072*5113495bSYour Name  * @data: Pointer to Spectral summary report
3073*5113495bSYour Name  * @fields: Pointer to structure to be populated with extracted fields
3074*5113495bSYour Name  * @spectral: Pointer to spectral object
3075*5113495bSYour Name  *
3076*5113495bSYour Name  * Consume Spectral summary report for gen3
3077*5113495bSYour Name  *
3078*5113495bSYour Name  * Return: QDF_STATUS
3079*5113495bSYour Name  */
3080*5113495bSYour Name static QDF_STATUS
target_if_consume_sscan_summary_report_gen3(uint8_t ** data,struct sscan_report_fields_gen3 * fields,struct target_if_spectral * spectral)3081*5113495bSYour Name target_if_consume_sscan_summary_report_gen3(
3082*5113495bSYour Name 				uint8_t **data,
3083*5113495bSYour Name 				struct sscan_report_fields_gen3 *fields,
3084*5113495bSYour Name 				struct target_if_spectral *spectral)
3085*5113495bSYour Name {
3086*5113495bSYour Name 	struct spectral_sscan_summary_report_gen3 *psscan_summary_report;
3087*5113495bSYour Name 	struct spectral_sscan_summary_report_padding_gen3_v2 *padding;
3088*5113495bSYour Name 	bool scan_radio_blanking;
3089*5113495bSYour Name 	QDF_STATUS ret;
3090*5113495bSYour Name 	uint8_t dtr_id;
3091*5113495bSYour Name 
3092*5113495bSYour Name 	if (!data) {
3093*5113495bSYour Name 		spectral_err_rl("Summary report buffer is null");
3094*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
3095*5113495bSYour Name 	}
3096*5113495bSYour Name 
3097*5113495bSYour Name 	if (!fields) {
3098*5113495bSYour Name 		spectral_err_rl("Invalid pointer to Summary report fields");
3099*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
3100*5113495bSYour Name 	}
3101*5113495bSYour Name 
3102*5113495bSYour Name 	if (!spectral) {
3103*5113495bSYour Name 		spectral_err_rl("Spectral LMAC object is null");
3104*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
3105*5113495bSYour Name 	}
3106*5113495bSYour Name 
3107*5113495bSYour Name 	/* Validate Spectral scan summary report */
3108*5113495bSYour Name 	if (target_if_verify_sig_and_tag_gen3(
3109*5113495bSYour Name 			spectral, *data,
3110*5113495bSYour Name 			TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN3) != 0) {
3111*5113495bSYour Name 		spectral_err_rl("Wrong tag/sig in sscan summary");
3112*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
3113*5113495bSYour Name 	}
3114*5113495bSYour Name 
3115*5113495bSYour Name 	ret = target_if_get_detector_id_sscan_summary_report_gen3(*data,
3116*5113495bSYour Name 								  &dtr_id);
3117*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(ret))
3118*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
3119*5113495bSYour Name 
3120*5113495bSYour Name 	fields->sscan_detector_id = dtr_id;
3121*5113495bSYour Name 	if (fields->sscan_detector_id >=
3122*5113495bSYour Name 	    spectral->rparams.num_spectral_detectors) {
3123*5113495bSYour Name 		spectral->diag_stats.spectral_invalid_detector_id++;
3124*5113495bSYour Name 		spectral_err_rl("Invalid detector id %u, expected is 0 to %u",
3125*5113495bSYour Name 				fields->sscan_detector_id,
3126*5113495bSYour Name 				spectral->rparams.num_spectral_detectors);
3127*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
3128*5113495bSYour Name 	}
3129*5113495bSYour Name 
3130*5113495bSYour Name 	psscan_summary_report =
3131*5113495bSYour Name 		(struct spectral_sscan_summary_report_gen3 *)*data;
3132*5113495bSYour Name 
3133*5113495bSYour Name 	fields->sscan_agc_total_gain = get_bitfield(
3134*5113495bSYour Name 			psscan_summary_report->hdr_a,
3135*5113495bSYour Name 			SSCAN_SUMMARY_REPORT_HDR_A_AGC_TOTAL_GAIN_SIZE_GEN3,
3136*5113495bSYour Name 			SSCAN_SUMMARY_REPORT_HDR_A_AGC_TOTAL_GAIN_POS_GEN3);
3137*5113495bSYour Name 	fields->inband_pwr_db = get_bitfield(
3138*5113495bSYour Name 			psscan_summary_report->hdr_a,
3139*5113495bSYour Name 			SSCAN_SUMMARY_REPORT_HDR_A_INBAND_PWR_DB_SIZE_GEN3,
3140*5113495bSYour Name 			SSCAN_SUMMARY_REPORT_HDR_A_INBAND_PWR_DB_POS_GEN3);
3141*5113495bSYour Name 	fields->sscan_pri80 = get_bitfield(
3142*5113495bSYour Name 			psscan_summary_report->hdr_a,
3143*5113495bSYour Name 			SSCAN_SUMMARY_REPORT_HDR_A_PRI80_SIZE_GEN3,
3144*5113495bSYour Name 			SSCAN_SUMMARY_REPORT_HDR_A_PRI80_POS_GEN3);
3145*5113495bSYour Name 
3146*5113495bSYour Name 	switch (spectral->rparams.version) {
3147*5113495bSYour Name 	case SPECTRAL_REPORT_FORMAT_VERSION_1:
3148*5113495bSYour Name 		fields->sscan_gainchange = get_bitfield(
3149*5113495bSYour Name 			psscan_summary_report->hdr_b,
3150*5113495bSYour Name 			SSCAN_SUMMARY_REPORT_HDR_B_GAINCHANGE_SIZE_GEN3_V1,
3151*5113495bSYour Name 			SSCAN_SUMMARY_REPORT_HDR_B_GAINCHANGE_POS_GEN3_V1);
3152*5113495bSYour Name 		break;
3153*5113495bSYour Name 	case SPECTRAL_REPORT_FORMAT_VERSION_2:
3154*5113495bSYour Name 		fields->sscan_gainchange = get_bitfield(
3155*5113495bSYour Name 			psscan_summary_report->hdr_c,
3156*5113495bSYour Name 			SSCAN_SUMMARY_REPORT_HDR_C_GAINCHANGE_SIZE_GEN3_V2,
3157*5113495bSYour Name 			SSCAN_SUMMARY_REPORT_HDR_C_GAINCHANGE_POS_GEN3_V2);
3158*5113495bSYour Name 		break;
3159*5113495bSYour Name 	default:
3160*5113495bSYour Name 		spectral_err_rl("Invalid spectral version: %d.",
3161*5113495bSYour Name 				spectral->rparams.version);
3162*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
3163*5113495bSYour Name 	}
3164*5113495bSYour Name 
3165*5113495bSYour Name 	/* Advance buf pointer to the search fft report */
3166*5113495bSYour Name 	*data += sizeof(struct spectral_sscan_summary_report_gen3);
3167*5113495bSYour Name 
3168*5113495bSYour Name 	if (!spectral->rparams.ssummary_padding_bytes)
3169*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
3170*5113495bSYour Name 
3171*5113495bSYour Name 	scan_radio_blanking =
3172*5113495bSYour Name 		wlan_pdev_nif_feat_ext_cap_get(spectral->pdev_obj,
3173*5113495bSYour Name 					       WLAN_PDEV_FEXT_SCAN_BLANKING_EN);
3174*5113495bSYour Name 	padding = (struct spectral_sscan_summary_report_padding_gen3_v2 *)*data;
3175*5113495bSYour Name 
3176*5113495bSYour Name 	if (scan_radio_blanking) {
3177*5113495bSYour Name 		uint32_t blanking_tag;
3178*5113495bSYour Name 		uint8_t blanking_tag_size;
3179*5113495bSYour Name 		uint8_t blanking_tag_pos;
3180*5113495bSYour Name 
3181*5113495bSYour Name 		blanking_tag_size =
3182*5113495bSYour Name 			SSCAN_SUMMARY_REPORT_PAD_HDR_A_BLANKING_SIZE_GEN3_V2;
3183*5113495bSYour Name 		blanking_tag_pos =
3184*5113495bSYour Name 			SSCAN_SUMMARY_REPORT_PAD_HDR_A_BLANKING_POS_GEN3_V2;
3185*5113495bSYour Name 		blanking_tag = get_bitfield(padding->hdr_a, blanking_tag_size,
3186*5113495bSYour Name 					    blanking_tag_pos);
3187*5113495bSYour Name 
3188*5113495bSYour Name 		if (blanking_tag ==
3189*5113495bSYour Name 		    SSCAN_SUMMARY_REPORT_PAD_HDR_A_BLANKING_TAG_GEN3_V2)
3190*5113495bSYour Name 			fields->blanking_status = 1;
3191*5113495bSYour Name 		else
3192*5113495bSYour Name 			fields->blanking_status = 0;
3193*5113495bSYour Name 	}
3194*5113495bSYour Name 
3195*5113495bSYour Name 	*data += sizeof(struct spectral_sscan_summary_report_padding_gen3_v2);
3196*5113495bSYour Name 
3197*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
3198*5113495bSYour Name }
3199*5113495bSYour Name 
3200*5113495bSYour Name /**
3201*5113495bSYour Name  * target_if_process_sfft_report_gen3() - Validate and Process Search
3202*5113495bSYour Name  * FFT Report for gen3
3203*5113495bSYour Name  * @data: Pointer to Spectral FFT report
3204*5113495bSYour Name  * @p_sfft: Pointer to search fft report
3205*5113495bSYour Name  * @spectral: Pointer to spectral object
3206*5113495bSYour Name  * @sscan_detector_id: Spectral detector id extracted from Summary report
3207*5113495bSYour Name  * @reset_delay: Time taken for warm reset in usec
3208*5113495bSYour Name  *
3209*5113495bSYour Name  * Validate and Process Search FFT Report for gen3
3210*5113495bSYour Name  *
3211*5113495bSYour Name  * Return: Success/Failure
3212*5113495bSYour Name  */
3213*5113495bSYour Name static QDF_STATUS
target_if_process_sfft_report_gen3(uint8_t * data,struct spectral_search_fft_info_gen3 * p_sfft,struct target_if_spectral * spectral,enum spectral_detector_id sscan_detector_id,uint32_t reset_delay)3214*5113495bSYour Name target_if_process_sfft_report_gen3(
3215*5113495bSYour Name 	uint8_t *data,
3216*5113495bSYour Name 	struct spectral_search_fft_info_gen3 *p_sfft,
3217*5113495bSYour Name 	struct target_if_spectral *spectral,
3218*5113495bSYour Name 	enum spectral_detector_id sscan_detector_id,
3219*5113495bSYour Name 	uint32_t reset_delay)
3220*5113495bSYour Name {
3221*5113495bSYour Name 	struct spectral_phyerr_fft_report_gen3 *p_fft_report;
3222*5113495bSYour Name 	int32_t peak_sidx = 0;
3223*5113495bSYour Name 	int32_t peak_mag;
3224*5113495bSYour Name 	int fft_hdr_length = 0;
3225*5113495bSYour Name 	uint32_t tstamp;
3226*5113495bSYour Name 	struct target_if_spectral_ops *p_sops;
3227*5113495bSYour Name 	enum spectral_scan_mode spectral_mode;
3228*5113495bSYour Name 	QDF_STATUS ret;
3229*5113495bSYour Name 
3230*5113495bSYour Name 	if (!data) {
3231*5113495bSYour Name 		spectral_err_rl("FFT report buffer is null");
3232*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
3233*5113495bSYour Name 	}
3234*5113495bSYour Name 
3235*5113495bSYour Name 	if (!p_sfft) {
3236*5113495bSYour Name 		spectral_err_rl("Invalid pointer to Search FFT report info");
3237*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
3238*5113495bSYour Name 	}
3239*5113495bSYour Name 
3240*5113495bSYour Name 	if (!spectral) {
3241*5113495bSYour Name 		spectral_err_rl("Spectral LMAC object is null");
3242*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
3243*5113495bSYour Name 	}
3244*5113495bSYour Name 
3245*5113495bSYour Name 	/*
3246*5113495bSYour Name 	 * For easy comparison between MDK team and OS team, the MDK script
3247*5113495bSYour Name 	 * variable names have been used
3248*5113495bSYour Name 	 */
3249*5113495bSYour Name 
3250*5113495bSYour Name 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
3251*5113495bSYour Name 
3252*5113495bSYour Name 	/* Validate Spectral search FFT report */
3253*5113495bSYour Name 	if (target_if_verify_sig_and_tag_gen3(
3254*5113495bSYour Name 			spectral, data, TLV_TAG_SEARCH_FFT_REPORT_GEN3) != 0) {
3255*5113495bSYour Name 		spectral_err_rl("Unexpected tag/sig in sfft, detid= %u",
3256*5113495bSYour Name 				sscan_detector_id);
3257*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
3258*5113495bSYour Name 	}
3259*5113495bSYour Name 
3260*5113495bSYour Name 	p_fft_report = (struct spectral_phyerr_fft_report_gen3 *)data;
3261*5113495bSYour Name 
3262*5113495bSYour Name 	fft_hdr_length = get_bitfield(
3263*5113495bSYour Name 			p_fft_report->fft_hdr_lts,
3264*5113495bSYour Name 			SPECTRAL_REPORT_LTS_HDR_LENGTH_SIZE_GEN3,
3265*5113495bSYour Name 			SPECTRAL_REPORT_LTS_HDR_LENGTH_POS_GEN3) * 4;
3266*5113495bSYour Name 	if (fft_hdr_length < 16) {
3267*5113495bSYour Name 		spectral_err("Wrong TLV length %u, detector id = %d",
3268*5113495bSYour Name 			     fft_hdr_length, sscan_detector_id);
3269*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
3270*5113495bSYour Name 	}
3271*5113495bSYour Name 
3272*5113495bSYour Name 	p_sfft->fft_detector_id = get_bitfield(
3273*5113495bSYour Name 					p_fft_report->hdr_a,
3274*5113495bSYour Name 					FFT_REPORT_HDR_A_DETECTOR_ID_SIZE_GEN3,
3275*5113495bSYour Name 					FFT_REPORT_HDR_A_DETECTOR_ID_POS_GEN3);
3276*5113495bSYour Name 
3277*5113495bSYour Name 	/* It is expected to have same detector id for
3278*5113495bSYour Name 	 * summary and fft report
3279*5113495bSYour Name 	 */
3280*5113495bSYour Name 	if (sscan_detector_id != p_sfft->fft_detector_id) {
3281*5113495bSYour Name 		spectral_err_rl("Different detid in ssummary(%u) and sfft(%u)",
3282*5113495bSYour Name 				sscan_detector_id, p_sfft->fft_detector_id);
3283*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
3284*5113495bSYour Name 	}
3285*5113495bSYour Name 
3286*5113495bSYour Name 	if (p_sfft->fft_detector_id >
3287*5113495bSYour Name 				spectral->rparams.num_spectral_detectors) {
3288*5113495bSYour Name 		spectral->diag_stats.spectral_invalid_detector_id++;
3289*5113495bSYour Name 		spectral_err("Invalid detector id %u, expected is 0 to %u",
3290*5113495bSYour Name 			     p_sfft->fft_detector_id,
3291*5113495bSYour Name 			     spectral->rparams.num_spectral_detectors);
3292*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
3293*5113495bSYour Name 	}
3294*5113495bSYour Name 
3295*5113495bSYour Name 	spectral_mode = target_if_get_spectral_mode(p_sfft->fft_detector_id,
3296*5113495bSYour Name 						    &spectral->rparams);
3297*5113495bSYour Name 	if (spectral_mode >= SPECTRAL_SCAN_MODE_MAX) {
3298*5113495bSYour Name 		spectral_err_rl("No valid Spectral mode for detector id %u",
3299*5113495bSYour Name 				p_sfft->fft_detector_id);
3300*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
3301*5113495bSYour Name 	}
3302*5113495bSYour Name 
3303*5113495bSYour Name 	/* Populate the Search FFT Info */
3304*5113495bSYour Name 	p_sfft->timestamp = p_fft_report->fft_timestamp;
3305*5113495bSYour Name 	p_sfft->last_raw_timestamp = spectral->timestamp_war.
3306*5113495bSYour Name 					last_fft_timestamp[spectral_mode];
3307*5113495bSYour Name 	ret = target_if_spectral_get_adjusted_timestamp(
3308*5113495bSYour Name 						&spectral->timestamp_war,
3309*5113495bSYour Name 						p_sfft->timestamp,
3310*5113495bSYour Name 						reset_delay,
3311*5113495bSYour Name 						spectral_mode,
3312*5113495bSYour Name 						&tstamp);
3313*5113495bSYour Name 
3314*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(ret))
3315*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
3316*5113495bSYour Name 
3317*5113495bSYour Name 	p_sfft->adjusted_timestamp =  tstamp;
3318*5113495bSYour Name 	/* Timestamp verification */
3319*5113495bSYour Name 	target_if_spectral_verify_ts(spectral, data,
3320*5113495bSYour Name 				     p_sfft->adjusted_timestamp,
3321*5113495bSYour Name 				     p_sfft->fft_detector_id);
3322*5113495bSYour Name 
3323*5113495bSYour Name 
3324*5113495bSYour Name 	p_sfft->fft_num = get_bitfield(p_fft_report->hdr_a,
3325*5113495bSYour Name 				       FFT_REPORT_HDR_A_FFT_NUM_SIZE_GEN3,
3326*5113495bSYour Name 				       FFT_REPORT_HDR_A_FFT_NUM_POS_GEN3);
3327*5113495bSYour Name 
3328*5113495bSYour Name 	switch (spectral->rparams.version) {
3329*5113495bSYour Name 	case SPECTRAL_REPORT_FORMAT_VERSION_1:
3330*5113495bSYour Name 		p_sfft->fft_radar_check = get_bitfield(p_fft_report->hdr_a,
3331*5113495bSYour Name 				FFT_REPORT_HDR_A_RADAR_CHECK_SIZE_GEN3_V1,
3332*5113495bSYour Name 				FFT_REPORT_HDR_A_RADAR_CHECK_POS_GEN3_V1);
3333*5113495bSYour Name 		peak_sidx = get_bitfield(
3334*5113495bSYour Name 				p_fft_report->hdr_a,
3335*5113495bSYour Name 				FFT_REPORT_HDR_A_PEAK_INDEX_SIZE_GEN3_V1,
3336*5113495bSYour Name 				FFT_REPORT_HDR_A_PEAK_INDEX_POS_GEN3_V1);
3337*5113495bSYour Name 		p_sfft->fft_chn_idx = get_bitfield(p_fft_report->hdr_a,
3338*5113495bSYour Name 				FFT_REPORT_HDR_A_CHAIN_INDEX_SIZE_GEN3_V1,
3339*5113495bSYour Name 				FFT_REPORT_HDR_A_CHAIN_INDEX_POS_GEN3_V1);
3340*5113495bSYour Name 		p_sfft->fft_base_pwr_db = get_bitfield(p_fft_report->hdr_b,
3341*5113495bSYour Name 				FFT_REPORT_HDR_B_BASE_PWR_SIZE_GEN3_V1,
3342*5113495bSYour Name 				FFT_REPORT_HDR_B_BASE_PWR_POS_GEN3_V1);
3343*5113495bSYour Name 		p_sfft->fft_total_gain_db = get_bitfield(p_fft_report->hdr_b,
3344*5113495bSYour Name 				FFT_REPORT_HDR_B_TOTAL_GAIN_SIZE_GEN3_V1,
3345*5113495bSYour Name 				FFT_REPORT_HDR_B_TOTAL_GAIN_POS_GEN3_V1);
3346*5113495bSYour Name 		break;
3347*5113495bSYour Name 	case SPECTRAL_REPORT_FORMAT_VERSION_2:
3348*5113495bSYour Name 		p_sfft->fft_radar_check = get_bitfield(p_fft_report->hdr_a,
3349*5113495bSYour Name 				FFT_REPORT_HDR_A_RADAR_CHECK_SIZE_GEN3_V2,
3350*5113495bSYour Name 				FFT_REPORT_HDR_A_RADAR_CHECK_POS_GEN3_V2);
3351*5113495bSYour Name 		peak_sidx = get_bitfield(
3352*5113495bSYour Name 				p_fft_report->hdr_a,
3353*5113495bSYour Name 				FFT_REPORT_HDR_A_PEAK_INDEX_SIZE_GEN3_V2,
3354*5113495bSYour Name 				FFT_REPORT_HDR_A_PEAK_INDEX_POS_GEN3_V2);
3355*5113495bSYour Name 		p_sfft->fft_chn_idx = get_bitfield(p_fft_report->hdr_b,
3356*5113495bSYour Name 				FFT_REPORT_HDR_B_CHAIN_INDEX_SIZE_GEN3_V2,
3357*5113495bSYour Name 				FFT_REPORT_HDR_B_CHAIN_INDEX_POS_GEN3_V2);
3358*5113495bSYour Name 		p_sfft->fft_base_pwr_db = get_bitfield(p_fft_report->hdr_b,
3359*5113495bSYour Name 				FFT_REPORT_HDR_B_BASE_PWR_SIZE_GEN3_V2,
3360*5113495bSYour Name 				FFT_REPORT_HDR_B_BASE_PWR_POS_GEN3_V2);
3361*5113495bSYour Name 		p_sfft->fft_total_gain_db = get_bitfield(p_fft_report->hdr_b,
3362*5113495bSYour Name 				FFT_REPORT_HDR_B_TOTAL_GAIN_SIZE_GEN3_V2,
3363*5113495bSYour Name 				FFT_REPORT_HDR_B_TOTAL_GAIN_POS_GEN3_V2);
3364*5113495bSYour Name 		break;
3365*5113495bSYour Name 	default:
3366*5113495bSYour Name 		spectral_err_rl("Invalid spectral version: %d.",
3367*5113495bSYour Name 				spectral->rparams.version);
3368*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
3369*5113495bSYour Name 	}
3370*5113495bSYour Name 
3371*5113495bSYour Name 	p_sfft->fft_peak_sidx = unsigned_to_signed(peak_sidx,
3372*5113495bSYour Name 				FFT_REPORT_HDR_A_PEAK_INDEX_SIZE_GEN3_V1);
3373*5113495bSYour Name 
3374*5113495bSYour Name 	p_sfft->fft_num_str_bins_ib = get_bitfield(p_fft_report->hdr_c,
3375*5113495bSYour Name 				FFT_REPORT_HDR_C_NUM_STRONG_BINS_SIZE_GEN3,
3376*5113495bSYour Name 				FFT_REPORT_HDR_C_NUM_STRONG_BINS_POS_GEN3);
3377*5113495bSYour Name 	peak_mag = get_bitfield(p_fft_report->hdr_c,
3378*5113495bSYour Name 				FFT_REPORT_HDR_C_PEAK_MAGNITUDE_SIZE_GEN3,
3379*5113495bSYour Name 				FFT_REPORT_HDR_C_PEAK_MAGNITUDE_POS_GEN3);
3380*5113495bSYour Name 	p_sfft->fft_peak_mag = unsigned_to_signed(peak_mag,
3381*5113495bSYour Name 				FFT_REPORT_HDR_C_PEAK_MAGNITUDE_SIZE_GEN3);
3382*5113495bSYour Name 	p_sfft->fft_avgpwr_db = get_bitfield(p_fft_report->hdr_c,
3383*5113495bSYour Name 				FFT_REPORT_HDR_C_AVG_PWR_SIZE_GEN3,
3384*5113495bSYour Name 				FFT_REPORT_HDR_C_AVG_PWR_POS_GEN3);
3385*5113495bSYour Name 	p_sfft->fft_relpwr_db = get_bitfield(p_fft_report->hdr_c,
3386*5113495bSYour Name 				FFT_REPORT_HDR_C_RELATIVE_PWR_SIZE_GEN3,
3387*5113495bSYour Name 				FFT_REPORT_HDR_C_RELATIVE_PWR_POS_GEN3);
3388*5113495bSYour Name 
3389*5113495bSYour Name 	p_sfft->fft_bin_count =
3390*5113495bSYour Name 		target_if_spectral_get_bin_count_after_len_adj(
3391*5113495bSYour Name 			fft_hdr_length - spectral->rparams.fft_report_hdr_len,
3392*5113495bSYour Name 			spectral->params[spectral_mode].ss_rpt_mode,
3393*5113495bSYour Name 			&spectral->len_adj_swar,
3394*5113495bSYour Name 			(size_t *)&p_sfft->fft_bin_size);
3395*5113495bSYour Name 
3396*5113495bSYour Name 	p_sfft->bin_pwr_data = (uint8_t *)p_fft_report + SPECTRAL_FFT_BINS_POS;
3397*5113495bSYour Name 
3398*5113495bSYour Name 	/* Apply byte-swap on the FFT bins.
3399*5113495bSYour Name 	 * NOTE: Until this point, bytes of the FFT bins could be in
3400*5113495bSYour Name 	 *       reverse order on a big-endian machine. If the consumers
3401*5113495bSYour Name 	 *       of FFT bins expects bytes in the correct order,
3402*5113495bSYour Name 	 *       they should use them only after this point.
3403*5113495bSYour Name 	 */
3404*5113495bSYour Name 	if (p_sops->byte_swap_fft_bins) {
3405*5113495bSYour Name 		ret = p_sops->byte_swap_fft_bins(&spectral->rparams,
3406*5113495bSYour Name 						 &p_sfft->bin_pwr_data,
3407*5113495bSYour Name 						 p_sfft->fft_bin_count);
3408*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(ret)) {
3409*5113495bSYour Name 			spectral_err_rl("Byte-swap on the FFT bins failed");
3410*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
3411*5113495bSYour Name 		}
3412*5113495bSYour Name 	}
3413*5113495bSYour Name 
3414*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
3415*5113495bSYour Name }
3416*5113495bSYour Name 
3417*5113495bSYour Name /**
3418*5113495bSYour Name  * target_if_spectral_populate_samp_params_gen3() - Populate the SAMP params
3419*5113495bSYour Name  * for gen3. SAMP params are to be used for populating SAMP msg.
3420*5113495bSYour Name  * @spectral: Pointer to spectral object
3421*5113495bSYour Name  * @p_sfft: Fields extracted from FFT report
3422*5113495bSYour Name  * @sscan_fields: Fields extracted from Summary report
3423*5113495bSYour Name  * @report: Pointer to spectral report
3424*5113495bSYour Name  * @params: Pointer to Spectral SAMP message fields to be populated
3425*5113495bSYour Name  *
3426*5113495bSYour Name  * Populate the SAMP params for gen3, which will be used to populate SAMP msg.
3427*5113495bSYour Name  *
3428*5113495bSYour Name  * Return: Success/Failure
3429*5113495bSYour Name  */
3430*5113495bSYour Name static QDF_STATUS
target_if_spectral_populate_samp_params_gen3(struct target_if_spectral * spectral,struct spectral_search_fft_info_gen3 * p_sfft,struct sscan_report_fields_gen3 * sscan_fields,struct spectral_report * report,struct target_if_samp_msg_params * params)3431*5113495bSYour Name target_if_spectral_populate_samp_params_gen3(
3432*5113495bSYour Name 		struct target_if_spectral *spectral,
3433*5113495bSYour Name 		struct spectral_search_fft_info_gen3 *p_sfft,
3434*5113495bSYour Name 		struct sscan_report_fields_gen3 *sscan_fields,
3435*5113495bSYour Name 		struct spectral_report *report,
3436*5113495bSYour Name 		struct target_if_samp_msg_params *params)
3437*5113495bSYour Name {
3438*5113495bSYour Name 	enum spectral_scan_mode spectral_mode;
3439*5113495bSYour Name 	uint8_t chn_idx_lowest_enabled;
3440*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
3441*5113495bSYour Name 	uint8_t vdev_rxchainmask;
3442*5113495bSYour Name 
3443*5113495bSYour Name 	if (!p_sfft) {
3444*5113495bSYour Name 		spectral_err_rl("Invalid pointer to Search FFT report info");
3445*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
3446*5113495bSYour Name 	}
3447*5113495bSYour Name 	if (!spectral) {
3448*5113495bSYour Name 		spectral_err_rl("Spectral LMAC object is null");
3449*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
3450*5113495bSYour Name 	}
3451*5113495bSYour Name 	if (!sscan_fields) {
3452*5113495bSYour Name 		spectral_err_rl("Invalid pointer to Summary report fields");
3453*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
3454*5113495bSYour Name 	}
3455*5113495bSYour Name 	if (!report) {
3456*5113495bSYour Name 		spectral_err_rl("Spectral report is null");
3457*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
3458*5113495bSYour Name 	}
3459*5113495bSYour Name 	if (!params) {
3460*5113495bSYour Name 		spectral_err_rl("SAMP msg params structure is null");
3461*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
3462*5113495bSYour Name 	}
3463*5113495bSYour Name 
3464*5113495bSYour Name 	/* RSSI is in 1/2 dBm steps, Convert it to dBm scale */
3465*5113495bSYour Name 	params->rssi = (sscan_fields->inband_pwr_db) >> 1;
3466*5113495bSYour Name 
3467*5113495bSYour Name 	params->hw_detector_id = p_sfft->fft_detector_id;
3468*5113495bSYour Name 	params->raw_timestamp = p_sfft->timestamp;
3469*5113495bSYour Name 	params->last_raw_timestamp = p_sfft->last_raw_timestamp;
3470*5113495bSYour Name 	params->timestamp = p_sfft->adjusted_timestamp;
3471*5113495bSYour Name 	params->reset_delay = report->reset_delay;
3472*5113495bSYour Name 
3473*5113495bSYour Name 	params->max_mag = p_sfft->fft_peak_mag;
3474*5113495bSYour Name 
3475*5113495bSYour Name 	spectral_mode = target_if_get_spectral_mode(params->hw_detector_id,
3476*5113495bSYour Name 						    &spectral->rparams);
3477*5113495bSYour Name 	vdev = target_if_spectral_get_vdev(spectral, spectral_mode);
3478*5113495bSYour Name 	if (!vdev) {
3479*5113495bSYour Name 		spectral_debug("First vdev is NULL");
3480*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
3481*5113495bSYour Name 	}
3482*5113495bSYour Name 	vdev_rxchainmask = wlan_vdev_mlme_get_rxchainmask(vdev);
3483*5113495bSYour Name 	if (vdev_rxchainmask == 0) {
3484*5113495bSYour Name 		spectral_err("Vdev rxchainmask is zero.");
3485*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
3486*5113495bSYour Name 	}
3487*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
3488*5113495bSYour Name 
3489*5113495bSYour Name 	chn_idx_lowest_enabled =
3490*5113495bSYour Name 		target_if_spectral_get_lowest_chn_idx(vdev_rxchainmask);
3491*5113495bSYour Name 	if (chn_idx_lowest_enabled >= DBR_MAX_CHAINS) {
3492*5113495bSYour Name 		spectral_err("Invalid chain index, detector id = %u",
3493*5113495bSYour Name 			     params->hw_detector_id);
3494*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
3495*5113495bSYour Name 	}
3496*5113495bSYour Name 	params->noise_floor = report->noisefloor[chn_idx_lowest_enabled];
3497*5113495bSYour Name 	params->agc_total_gain = sscan_fields->sscan_agc_total_gain;
3498*5113495bSYour Name 	params->gainchange = sscan_fields->sscan_gainchange;
3499*5113495bSYour Name 	params->blanking_status = sscan_fields->blanking_status;
3500*5113495bSYour Name 	params->pri80ind = sscan_fields->sscan_pri80;
3501*5113495bSYour Name 
3502*5113495bSYour Name 	params->bin_pwr_data = p_sfft->bin_pwr_data;
3503*5113495bSYour Name 
3504*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
3505*5113495bSYour Name }
3506*5113495bSYour Name 
3507*5113495bSYour Name int
target_if_consume_spectral_report_gen3(struct target_if_spectral * spectral,struct spectral_report * report)3508*5113495bSYour Name target_if_consume_spectral_report_gen3(
3509*5113495bSYour Name 	 struct target_if_spectral *spectral,
3510*5113495bSYour Name 	 struct spectral_report *report)
3511*5113495bSYour Name {
3512*5113495bSYour Name 	/*
3513*5113495bSYour Name 	 * XXX : The classifier do not use all the members of the SAMP
3514*5113495bSYour Name 	 *       message data format.
3515*5113495bSYour Name 	 *       The classifier only depends upon the following parameters
3516*5113495bSYour Name 	 *
3517*5113495bSYour Name 	 *          1. Frequency
3518*5113495bSYour Name 	 *          2. Spectral RSSI
3519*5113495bSYour Name 	 *          3. Bin Power Count
3520*5113495bSYour Name 	 *          4. Bin Power values
3521*5113495bSYour Name 	 *          5. Spectral Timestamp
3522*5113495bSYour Name 	 *          6. MAC Address
3523*5113495bSYour Name 	 *
3524*5113495bSYour Name 	 *       This function processes the Spectral summary and FFT reports
3525*5113495bSYour Name 	 *       and passes the processed information
3526*5113495bSYour Name 	 *       target_if_spectral_fill_samp_msg()
3527*5113495bSYour Name 	 *       to prepare fully formatted Spectral SAMP message
3528*5113495bSYour Name 	 *
3529*5113495bSYour Name 	 *       XXX : Need to verify
3530*5113495bSYour Name 	 *          1. Order of FFT bin values
3531*5113495bSYour Name 	 *
3532*5113495bSYour Name 	 */
3533*5113495bSYour Name 	struct target_if_samp_msg_params params = {0};
3534*5113495bSYour Name 	struct spectral_search_fft_info_gen3 search_fft_info;
3535*5113495bSYour Name 	struct spectral_search_fft_info_gen3 *p_sfft = &search_fft_info;
3536*5113495bSYour Name 	struct target_if_spectral_ops *p_sops;
3537*5113495bSYour Name 	struct spectral_phyerr_fft_report_gen3 *p_fft_report;
3538*5113495bSYour Name 	uint8_t *data;
3539*5113495bSYour Name 	struct sscan_report_fields_gen3 sscan_report_fields = {0};
3540*5113495bSYour Name 	QDF_STATUS ret;
3541*5113495bSYour Name 	enum spectral_scan_mode spectral_mode = SPECTRAL_SCAN_MODE_INVALID;
3542*5113495bSYour Name 	bool finite_scan = false;
3543*5113495bSYour Name 	int det = 0;
3544*5113495bSYour Name 	struct sscan_detector_list *det_list;
3545*5113495bSYour Name 	struct spectral_data_stats *spectral_dp_stats;
3546*5113495bSYour Name 	bool print_fail_msg = true;
3547*5113495bSYour Name 
3548*5113495bSYour Name 	if (!spectral) {
3549*5113495bSYour Name 		spectral_err_rl("Spectral LMAC object is null");
3550*5113495bSYour Name 		print_fail_msg = false;
3551*5113495bSYour Name 		goto fail;
3552*5113495bSYour Name 	}
3553*5113495bSYour Name 
3554*5113495bSYour Name 	qdf_spin_lock_bh(&spectral->spectral_lock);
3555*5113495bSYour Name 	spectral_dp_stats = &spectral->data_stats;
3556*5113495bSYour Name 	spectral_dp_stats->consume_spectral_calls++;
3557*5113495bSYour Name 
3558*5113495bSYour Name 	if (!report) {
3559*5113495bSYour Name 		spectral_err_rl("Spectral report is null");
3560*5113495bSYour Name 		print_fail_msg = false;
3561*5113495bSYour Name 		goto fail_unlock;
3562*5113495bSYour Name 	}
3563*5113495bSYour Name 
3564*5113495bSYour Name 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
3565*5113495bSYour Name 	data = report->data;
3566*5113495bSYour Name 
3567*5113495bSYour Name 	/* Apply byte-swap on the headers */
3568*5113495bSYour Name 	if (p_sops->byte_swap_headers) {
3569*5113495bSYour Name 		ret = p_sops->byte_swap_headers(spectral, data);
3570*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(ret)) {
3571*5113495bSYour Name 			spectral_err_rl("Byte-swap on Spectral headers failed");
3572*5113495bSYour Name 			goto fail_unlock;
3573*5113495bSYour Name 		}
3574*5113495bSYour Name 	}
3575*5113495bSYour Name 
3576*5113495bSYour Name 	/* Validate and Process Spectral scan summary report */
3577*5113495bSYour Name 	ret = target_if_consume_sscan_summary_report_gen3(&data,
3578*5113495bSYour Name 							  &sscan_report_fields,
3579*5113495bSYour Name 							  spectral);
3580*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(ret)) {
3581*5113495bSYour Name 		spectral_err_rl("Failed to process Spectral summary report");
3582*5113495bSYour Name 		goto fail_unlock;
3583*5113495bSYour Name 	}
3584*5113495bSYour Name 
3585*5113495bSYour Name 	spectral_mode = target_if_get_spectral_mode(
3586*5113495bSYour Name 					sscan_report_fields.sscan_detector_id,
3587*5113495bSYour Name 					&spectral->rparams);
3588*5113495bSYour Name 	if (spectral_mode >= SPECTRAL_SCAN_MODE_MAX) {
3589*5113495bSYour Name 		spectral_err_rl("No valid Spectral mode for detector id %u",
3590*5113495bSYour Name 				sscan_report_fields.sscan_detector_id);
3591*5113495bSYour Name 		goto fail_unlock;
3592*5113495bSYour Name 	}
3593*5113495bSYour Name 
3594*5113495bSYour Name 	/* Drop the sample if Spectral is not active for the current mode */
3595*5113495bSYour Name 	if (!p_sops->is_spectral_active(spectral, spectral_mode)) {
3596*5113495bSYour Name 		spectral_info_rl("Spectral scan is not active");
3597*5113495bSYour Name 		print_fail_msg = false;
3598*5113495bSYour Name 		goto fail_unlock;
3599*5113495bSYour Name 	}
3600*5113495bSYour Name 
3601*5113495bSYour Name 	/* Validate and Process the search FFT report */
3602*5113495bSYour Name 	ret = target_if_process_sfft_report_gen3(
3603*5113495bSYour Name 					data, p_sfft,
3604*5113495bSYour Name 					spectral,
3605*5113495bSYour Name 					sscan_report_fields.sscan_detector_id,
3606*5113495bSYour Name 					report->reset_delay);
3607*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(ret)) {
3608*5113495bSYour Name 		spectral_err_rl("Failed to process search FFT report");
3609*5113495bSYour Name 		goto fail_unlock;
3610*5113495bSYour Name 	}
3611*5113495bSYour Name 
3612*5113495bSYour Name 	qdf_spin_lock_bh(&spectral->detector_list_lock);
3613*5113495bSYour Name 	det_list = &spectral->detector_list[spectral_mode]
3614*5113495bSYour Name 			[spectral->report_info[spectral_mode].sscan_bw];
3615*5113495bSYour Name 	for (det = 0; det < det_list->num_detectors; det++) {
3616*5113495bSYour Name 		if (p_sfft->fft_detector_id == det_list->detectors[det])
3617*5113495bSYour Name 			break;
3618*5113495bSYour Name 		if (det == det_list->num_detectors - 1) {
3619*5113495bSYour Name 			qdf_spin_unlock_bh(&spectral->detector_list_lock);
3620*5113495bSYour Name 			spectral_info("Incorrect det id %d for given scan mode and channel width",
3621*5113495bSYour Name 				      p_sfft->fft_detector_id);
3622*5113495bSYour Name 			print_fail_msg = false;
3623*5113495bSYour Name 			goto fail_unlock;
3624*5113495bSYour Name 		}
3625*5113495bSYour Name 	}
3626*5113495bSYour Name 	qdf_spin_unlock_bh(&spectral->detector_list_lock);
3627*5113495bSYour Name 
3628*5113495bSYour Name 	ret = target_if_update_session_info_from_report_ctx(
3629*5113495bSYour Name 						spectral,
3630*5113495bSYour Name 						p_sfft->fft_bin_size,
3631*5113495bSYour Name 						report->cfreq1, report->cfreq2,
3632*5113495bSYour Name 						spectral_mode);
3633*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(ret)) {
3634*5113495bSYour Name 		spectral_err_rl("Failed to update per-session info");
3635*5113495bSYour Name 		goto fail_unlock;
3636*5113495bSYour Name 	}
3637*5113495bSYour Name 
3638*5113495bSYour Name 	qdf_spin_lock_bh(&spectral->session_report_info_lock);
3639*5113495bSYour Name 	/* Check FFT report are in order for 160 MHz and 80p80 */
3640*5113495bSYour Name 	if (is_ch_width_160_or_80p80(
3641*5113495bSYour Name 	    spectral->report_info[spectral_mode].sscan_bw) &&
3642*5113495bSYour Name 	    spectral->rparams.fragmentation_160[spectral_mode]) {
3643*5113495bSYour Name 		ret = target_if_160mhz_delivery_state_change(
3644*5113495bSYour Name 				spectral, spectral_mode,
3645*5113495bSYour Name 				p_sfft->fft_detector_id);
3646*5113495bSYour Name 		if (ret != QDF_STATUS_SUCCESS) {
3647*5113495bSYour Name 			qdf_spin_unlock_bh(
3648*5113495bSYour Name 					&spectral->session_report_info_lock);
3649*5113495bSYour Name 			goto fail_unlock;
3650*5113495bSYour Name 		}
3651*5113495bSYour Name 	}
3652*5113495bSYour Name 	qdf_spin_unlock_bh(&spectral->session_report_info_lock);
3653*5113495bSYour Name 
3654*5113495bSYour Name 	p_fft_report = (struct spectral_phyerr_fft_report_gen3 *)data;
3655*5113495bSYour Name 	if (spectral_debug_level & (DEBUG_SPECTRAL2 | DEBUG_SPECTRAL4))
3656*5113495bSYour Name 		target_if_dump_fft_report_gen3(spectral, spectral_mode,
3657*5113495bSYour Name 					       p_fft_report, p_sfft);
3658*5113495bSYour Name 
3659*5113495bSYour Name 	target_if_spectral_check_buffer_poisoning(spectral, report,
3660*5113495bSYour Name 						  p_sfft->fft_bin_count,
3661*5113495bSYour Name 						  spectral_mode);
3662*5113495bSYour Name 
3663*5113495bSYour Name 	/* Populate SAMP params */
3664*5113495bSYour Name 	ret = target_if_spectral_populate_samp_params_gen3(
3665*5113495bSYour Name 							spectral, p_sfft,
3666*5113495bSYour Name 							&sscan_report_fields,
3667*5113495bSYour Name 							report, &params);
3668*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(ret)) {
3669*5113495bSYour Name 		spectral_err_rl("Failed to populate SAMP params");
3670*5113495bSYour Name 		goto fail_unlock;
3671*5113495bSYour Name 	}
3672*5113495bSYour Name 
3673*5113495bSYour Name 	/* Fill SAMP message */
3674*5113495bSYour Name 	ret = target_if_spectral_fill_samp_msg(spectral, &params);
3675*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(ret)) {
3676*5113495bSYour Name 		spectral_err_rl("Failed to fill the SAMP msg");
3677*5113495bSYour Name 		goto fail_unlock;
3678*5113495bSYour Name 	}
3679*5113495bSYour Name 
3680*5113495bSYour Name 	qdf_spin_unlock_bh(&spectral->spectral_lock);
3681*5113495bSYour Name 	ret = target_if_spectral_is_finite_scan(spectral, spectral_mode,
3682*5113495bSYour Name 						&finite_scan);
3683*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(ret)) {
3684*5113495bSYour Name 		spectral_err_rl("Failed to check scan is finite");
3685*5113495bSYour Name 		goto fail;
3686*5113495bSYour Name 	}
3687*5113495bSYour Name 
3688*5113495bSYour Name 	if (finite_scan) {
3689*5113495bSYour Name 		ret = target_if_spectral_finite_scan_update(spectral,
3690*5113495bSYour Name 							    spectral_mode);
3691*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(ret)) {
3692*5113495bSYour Name 			spectral_err_rl("Failed to update scan count");
3693*5113495bSYour Name 			goto fail;
3694*5113495bSYour Name 		}
3695*5113495bSYour Name 	}
3696*5113495bSYour Name 
3697*5113495bSYour Name 	return 0;
3698*5113495bSYour Name fail_unlock:
3699*5113495bSYour Name 	qdf_spin_unlock_bh(&spectral->spectral_lock);
3700*5113495bSYour Name fail:
3701*5113495bSYour Name 	if (print_fail_msg)
3702*5113495bSYour Name 		spectral_err_rl("Error while processing Spectral report");
3703*5113495bSYour Name 
3704*5113495bSYour Name 	if (spectral_mode != SPECTRAL_SCAN_MODE_INVALID)
3705*5113495bSYour Name 		reset_160mhz_delivery_state_machine(spectral, spectral_mode);
3706*5113495bSYour Name 	return -EPERM;
3707*5113495bSYour Name }
3708*5113495bSYour Name 
3709*5113495bSYour Name #else
3710*5113495bSYour Name int
target_if_consume_spectral_report_gen3(struct target_if_spectral * spectral,struct spectral_report * report)3711*5113495bSYour Name target_if_consume_spectral_report_gen3(
3712*5113495bSYour Name 	 struct target_if_spectral *spectral,
3713*5113495bSYour Name 	 struct spectral_report *report)
3714*5113495bSYour Name {
3715*5113495bSYour Name 	/*
3716*5113495bSYour Name 	 * XXX : The classifier do not use all the members of the SAMP
3717*5113495bSYour Name 	 *       message data format.
3718*5113495bSYour Name 	 *       The classifier only depends upon the following parameters
3719*5113495bSYour Name 	 *
3720*5113495bSYour Name 	 *          1. Frequency (freq, msg->freq)
3721*5113495bSYour Name 	 *          2. Spectral RSSI (spectral_rssi,
3722*5113495bSYour Name 	 *          msg->samp_data.spectral_rssi)
3723*5113495bSYour Name 	 *          3. Bin Power Count (bin_pwr_count,
3724*5113495bSYour Name 	 *          msg->samp_data.bin_pwr_count)
3725*5113495bSYour Name 	 *          4. Bin Power values (bin_pwr, msg->samp_data.bin_pwr[0]
3726*5113495bSYour Name 	 *          5. Spectral Timestamp (spectral_tstamp,
3727*5113495bSYour Name 	 *          msg->samp_data.spectral_tstamp)
3728*5113495bSYour Name 	 *          6. MAC Address (macaddr, msg->macaddr)
3729*5113495bSYour Name 	 *
3730*5113495bSYour Name 	 *       This function prepares the params structure and populates it
3731*5113495bSYour Name 	 *       with
3732*5113495bSYour Name 	 *       relevant values, this is in turn passed to
3733*5113495bSYour Name 	 *       spectral_create_samp_msg()
3734*5113495bSYour Name 	 *       to prepare fully formatted Spectral SAMP message
3735*5113495bSYour Name 	 *
3736*5113495bSYour Name 	 *       XXX : Need to verify
3737*5113495bSYour Name 	 *          1. Order of FFT bin values
3738*5113495bSYour Name 	 *
3739*5113495bSYour Name 	 */
3740*5113495bSYour Name 	struct target_if_samp_msg_params params = {0};
3741*5113495bSYour Name 	struct spectral_search_fft_info_gen3 search_fft_info;
3742*5113495bSYour Name 	struct spectral_search_fft_info_gen3 *p_sfft = &search_fft_info;
3743*5113495bSYour Name 	int8_t chn_idx_lowest_enabled  = 0;
3744*5113495bSYour Name 	int fft_hdr_length = 0;
3745*5113495bSYour Name 	int report_len = 0;
3746*5113495bSYour Name 	size_t fft_bin_count;
3747*5113495bSYour Name 	size_t fft_bin_size;
3748*5113495bSYour Name 	struct target_if_spectral_ops *p_sops =
3749*5113495bSYour Name 		GET_TARGET_IF_SPECTRAL_OPS(spectral);
3750*5113495bSYour Name 	struct spectral_phyerr_fft_report_gen3 *p_fft_report;
3751*5113495bSYour Name 	int8_t rssi;
3752*5113495bSYour Name 	uint8_t *data = report->data;
3753*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
3754*5113495bSYour Name 	uint8_t vdev_rxchainmask;
3755*5113495bSYour Name 	struct sscan_report_fields_gen3 sscan_report_fields = {0};
3756*5113495bSYour Name 	enum spectral_detector_id detector_id;
3757*5113495bSYour Name 	uint8_t dtr_id;
3758*5113495bSYour Name 	QDF_STATUS ret;
3759*5113495bSYour Name 	enum spectral_scan_mode spectral_mode = SPECTRAL_SCAN_MODE_INVALID;
3760*5113495bSYour Name 	uint8_t *temp;
3761*5113495bSYour Name 	bool finite_scan = false;
3762*5113495bSYour Name 	uint32_t tstamp;
3763*5113495bSYour Name 
3764*5113495bSYour Name 	/* Apply byte-swap on the headers */
3765*5113495bSYour Name 	if (p_sops->byte_swap_headers) {
3766*5113495bSYour Name 		ret = p_sops->byte_swap_headers(spectral, data);
3767*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(ret)) {
3768*5113495bSYour Name 			spectral_err_rl("Byte-swap on Spectral headers failed");
3769*5113495bSYour Name 			goto fail;
3770*5113495bSYour Name 		}
3771*5113495bSYour Name 	}
3772*5113495bSYour Name 
3773*5113495bSYour Name 	/* Process Spectral scan summary report */
3774*5113495bSYour Name 	if (target_if_verify_sig_and_tag_gen3(
3775*5113495bSYour Name 			spectral, data,
3776*5113495bSYour Name 			TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN3) != 0) {
3777*5113495bSYour Name 		spectral_err_rl("Wrong tag/sig in sscan summary");
3778*5113495bSYour Name 		goto fail;
3779*5113495bSYour Name 	}
3780*5113495bSYour Name 
3781*5113495bSYour Name 	ret = target_if_get_detector_id_sscan_summary_report_gen3(data,
3782*5113495bSYour Name 								  &dtr_id);
3783*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(ret))
3784*5113495bSYour Name 		goto fail;
3785*5113495bSYour Name 
3786*5113495bSYour Name 	detector_id = dtr_id;
3787*5113495bSYour Name 	if (detector_id >= spectral->rparams.num_spectral_detectors) {
3788*5113495bSYour Name 		spectral->diag_stats.spectral_invalid_detector_id++;
3789*5113495bSYour Name 		spectral_err("Invalid detector id %u, expected is 0/1/2",
3790*5113495bSYour Name 			     detector_id);
3791*5113495bSYour Name 		goto fail;
3792*5113495bSYour Name 	}
3793*5113495bSYour Name 
3794*5113495bSYour Name 	spectral_mode = target_if_get_spectral_mode(detector_id,
3795*5113495bSYour Name 						    &spectral->rparams);
3796*5113495bSYour Name 	if (spectral_mode >= SPECTRAL_SCAN_MODE_MAX) {
3797*5113495bSYour Name 		spectral_err_rl("No valid Spectral mode for detector id %u",
3798*5113495bSYour Name 				detector_id);
3799*5113495bSYour Name 		goto fail;
3800*5113495bSYour Name 	}
3801*5113495bSYour Name 
3802*5113495bSYour Name 	/* Drop the sample if Spectral is not active for the current mode */
3803*5113495bSYour Name 	if (!p_sops->is_spectral_active(spectral, spectral_mode)) {
3804*5113495bSYour Name 		spectral_info_rl("Spectral scan is not active");
3805*5113495bSYour Name 		goto fail_no_print;
3806*5113495bSYour Name 	}
3807*5113495bSYour Name 
3808*5113495bSYour Name 	ret = target_if_spectral_is_finite_scan(spectral, spectral_mode,
3809*5113495bSYour Name 						&finite_scan);
3810*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(ret)) {
3811*5113495bSYour Name 		spectral_err_rl("Failed to check scan is finite");
3812*5113495bSYour Name 		goto fail;
3813*5113495bSYour Name 	}
3814*5113495bSYour Name 
3815*5113495bSYour Name 	if (finite_scan) {
3816*5113495bSYour Name 		ret = target_if_spectral_finite_scan_update(spectral,
3817*5113495bSYour Name 							    spectral_mode);
3818*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(ret)) {
3819*5113495bSYour Name 			spectral_err_rl("Failed to update scan count");
3820*5113495bSYour Name 			goto fail;
3821*5113495bSYour Name 		}
3822*5113495bSYour Name 	}
3823*5113495bSYour Name 
3824*5113495bSYour Name 	target_if_consume_sscan_summary_report_gen3(data, &sscan_report_fields,
3825*5113495bSYour Name 						    &spectral->rparams);
3826*5113495bSYour Name 	/* Advance buf pointer to the search fft report */
3827*5113495bSYour Name 	data += sizeof(struct spectral_sscan_summary_report_gen3);
3828*5113495bSYour Name 	data += spectral->rparams.ssummary_padding_bytes;
3829*5113495bSYour Name 	params.vhtop_ch_freq_seg1 = report->cfreq1;
3830*5113495bSYour Name 	params.vhtop_ch_freq_seg2 = report->cfreq2;
3831*5113495bSYour Name 
3832*5113495bSYour Name 	if (is_primaryseg_expected(spectral, spectral_mode)) {
3833*5113495bSYour Name 		/* RSSI is in 1/2 dBm steps, Convert it to dBm scale */
3834*5113495bSYour Name 		rssi = (sscan_report_fields.inband_pwr_db) >> 1;
3835*5113495bSYour Name 		params.agc_total_gain =
3836*5113495bSYour Name 			sscan_report_fields.sscan_agc_total_gain;
3837*5113495bSYour Name 		params.gainchange = sscan_report_fields.sscan_gainchange;
3838*5113495bSYour Name 		params.pri80ind = sscan_report_fields.sscan_pri80;
3839*5113495bSYour Name 
3840*5113495bSYour Name 		/* Process Spectral search FFT report */
3841*5113495bSYour Name 		if (target_if_verify_sig_and_tag_gen3(
3842*5113495bSYour Name 				spectral, data,
3843*5113495bSYour Name 				TLV_TAG_SEARCH_FFT_REPORT_GEN3) != 0) {
3844*5113495bSYour Name 			spectral_err_rl("Unexpected tag/sig in sfft, detid= %u",
3845*5113495bSYour Name 					detector_id);
3846*5113495bSYour Name 			goto fail;
3847*5113495bSYour Name 		}
3848*5113495bSYour Name 		p_fft_report = (struct spectral_phyerr_fft_report_gen3 *)data;
3849*5113495bSYour Name 		fft_hdr_length = get_bitfield(
3850*5113495bSYour Name 				p_fft_report->fft_hdr_lts,
3851*5113495bSYour Name 				SPECTRAL_REPORT_LTS_HDR_LENGTH_SIZE_GEN3,
3852*5113495bSYour Name 				SPECTRAL_REPORT_LTS_HDR_LENGTH_POS_GEN3) * 4;
3853*5113495bSYour Name 		if (fft_hdr_length < 16) {
3854*5113495bSYour Name 			spectral_err("Wrong TLV length %u, detector id = %d",
3855*5113495bSYour Name 				     fft_hdr_length, detector_id);
3856*5113495bSYour Name 			goto fail;
3857*5113495bSYour Name 		}
3858*5113495bSYour Name 
3859*5113495bSYour Name 		report_len = (fft_hdr_length + 8);
3860*5113495bSYour Name 
3861*5113495bSYour Name 		target_if_process_sfft_report_gen3(p_fft_report, p_sfft,
3862*5113495bSYour Name 						   &spectral->rparams);
3863*5113495bSYour Name 		/* It is expected to have same detector id for
3864*5113495bSYour Name 		 * summary and fft report
3865*5113495bSYour Name 		 */
3866*5113495bSYour Name 		if (detector_id != p_sfft->fft_detector_id) {
3867*5113495bSYour Name 			spectral_err_rl
3868*5113495bSYour Name 				("Different detid in ssummary(%u) and sfft(%u)",
3869*5113495bSYour Name 				 detector_id, p_sfft->fft_detector_id);
3870*5113495bSYour Name 			goto fail;
3871*5113495bSYour Name 		}
3872*5113495bSYour Name 
3873*5113495bSYour Name 		if (detector_id > spectral->rparams.num_spectral_detectors) {
3874*5113495bSYour Name 			spectral->diag_stats.spectral_invalid_detector_id++;
3875*5113495bSYour Name 			spectral_err("Invalid detector id %u, expected is 0/2",
3876*5113495bSYour Name 				     detector_id);
3877*5113495bSYour Name 			goto fail;
3878*5113495bSYour Name 		}
3879*5113495bSYour Name 		params.smode = spectral_mode;
3880*5113495bSYour Name 
3881*5113495bSYour Name 		fft_bin_count = target_if_spectral_get_bin_count_after_len_adj(
3882*5113495bSYour Name 			fft_hdr_length - spectral->rparams.fft_report_hdr_len,
3883*5113495bSYour Name 			spectral->params[spectral_mode].ss_rpt_mode,
3884*5113495bSYour Name 			&spectral->len_adj_swar, &fft_bin_size);
3885*5113495bSYour Name 
3886*5113495bSYour Name 		params.last_raw_timestamp = spectral->timestamp_war.
3887*5113495bSYour Name 				last_fft_timestamp[spectral_mode];
3888*5113495bSYour Name 		params.reset_delay = report->reset_delay;
3889*5113495bSYour Name 		params.raw_timestamp = p_sfft->timestamp;
3890*5113495bSYour Name 		ret = target_if_spectral_get_adjusted_timestamp(
3891*5113495bSYour Name 					&spectral->timestamp_war,
3892*5113495bSYour Name 					p_sfft->timestamp, report->reset_delay,
3893*5113495bSYour Name 					spectral_mode, &tstamp);
3894*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(ret))
3895*5113495bSYour Name 			goto fail;
3896*5113495bSYour Name 
3897*5113495bSYour Name 		params.tstamp = tstamp;
3898*5113495bSYour Name 		params.timestamp_war_offset = spectral->timestamp_war.
3899*5113495bSYour Name 				timestamp_war_offset[spectral_mode];
3900*5113495bSYour Name 		params.target_reset_count = spectral->timestamp_war.
3901*5113495bSYour Name 				target_reset_count;
3902*5113495bSYour Name 
3903*5113495bSYour Name 		/* Take care of state transitions for 160 MHz and 80p80 */
3904*5113495bSYour Name 		if (is_ch_width_160_or_80p80(spectral->ch_width
3905*5113495bSYour Name 		    [spectral_mode]) && spectral->rparams.
3906*5113495bSYour Name 		    fragmentation_160[spectral_mode]) {
3907*5113495bSYour Name 			ret = target_if_160mhz_delivery_state_change(
3908*5113495bSYour Name 					spectral, spectral_mode,
3909*5113495bSYour Name 					detector_id);
3910*5113495bSYour Name 			if (ret != QDF_STATUS_SUCCESS)
3911*5113495bSYour Name 				goto fail;
3912*5113495bSYour Name 		}
3913*5113495bSYour Name 
3914*5113495bSYour Name 		params.rssi         = rssi;
3915*5113495bSYour Name 
3916*5113495bSYour Name 		vdev = target_if_spectral_get_vdev(spectral, spectral_mode);
3917*5113495bSYour Name 		if (!vdev) {
3918*5113495bSYour Name 			spectral_debug("First vdev is NULL");
3919*5113495bSYour Name 			reset_160mhz_delivery_state_machine(
3920*5113495bSYour Name 						spectral, spectral_mode);
3921*5113495bSYour Name 			return -EPERM;
3922*5113495bSYour Name 		}
3923*5113495bSYour Name 		vdev_rxchainmask = wlan_vdev_mlme_get_rxchainmask(vdev);
3924*5113495bSYour Name 		if (vdev_rxchainmask == 0) {
3925*5113495bSYour Name 			spectral_err("Vdev rxchainmask is zero.");
3926*5113495bSYour Name 			goto fail;
3927*5113495bSYour Name 		}
3928*5113495bSYour Name 		wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
3929*5113495bSYour Name 
3930*5113495bSYour Name 		chn_idx_lowest_enabled =
3931*5113495bSYour Name 		target_if_spectral_get_lowest_chn_idx(vdev_rxchainmask);
3932*5113495bSYour Name 		if (chn_idx_lowest_enabled >= DBR_MAX_CHAINS) {
3933*5113495bSYour Name 			spectral_err("Invalid chain index, detector id = %u",
3934*5113495bSYour Name 				     detector_id);
3935*5113495bSYour Name 			goto fail;
3936*5113495bSYour Name 		}
3937*5113495bSYour Name 
3938*5113495bSYour Name 		params.max_mag  = p_sfft->fft_peak_mag;
3939*5113495bSYour Name 
3940*5113495bSYour Name 		params.freq = p_sops->get_current_channel(spectral,
3941*5113495bSYour Name 							  spectral_mode);
3942*5113495bSYour Name 		params.agile_freq1 = spectral->params[SPECTRAL_SCAN_MODE_AGILE].
3943*5113495bSYour Name 				     ss_frequency.cfreq1;
3944*5113495bSYour Name 		params.agile_freq2 = spectral->params[SPECTRAL_SCAN_MODE_AGILE].
3945*5113495bSYour Name 				     ss_frequency.cfreq2;
3946*5113495bSYour Name 		params.noise_floor =
3947*5113495bSYour Name 			report->noisefloor[chn_idx_lowest_enabled];
3948*5113495bSYour Name 		temp = (uint8_t *)p_fft_report + SPECTRAL_FFT_BINS_POS;
3949*5113495bSYour Name 		if (is_ch_width_160_or_80p80(spectral->ch_width
3950*5113495bSYour Name 		    [spectral_mode]) && !spectral->rparams.
3951*5113495bSYour Name 		    fragmentation_160[spectral_mode]) {
3952*5113495bSYour Name 			struct wlan_objmgr_psoc *psoc;
3953*5113495bSYour Name 			struct spectral_fft_bin_markers_160_165mhz *marker;
3954*5113495bSYour Name 
3955*5113495bSYour Name 			if (!spectral->pdev_obj) {
3956*5113495bSYour Name 				spectral_err("pdev is null");
3957*5113495bSYour Name 				goto fail;
3958*5113495bSYour Name 			}
3959*5113495bSYour Name 			psoc = wlan_pdev_get_psoc(spectral->pdev_obj);
3960*5113495bSYour Name 			if (!psoc) {
3961*5113495bSYour Name 				spectral_err("psoc is null");
3962*5113495bSYour Name 				goto fail;
3963*5113495bSYour Name 			}
3964*5113495bSYour Name 			params.agc_total_gain_sec80 =
3965*5113495bSYour Name 				sscan_report_fields.sscan_agc_total_gain;
3966*5113495bSYour Name 			params.gainchange_sec80 =
3967*5113495bSYour Name 					sscan_report_fields.sscan_gainchange;
3968*5113495bSYour Name 			params.raw_timestamp_sec80 = p_sfft->timestamp;
3969*5113495bSYour Name 			params.rssi_sec80 = rssi;
3970*5113495bSYour Name 			params.noise_floor_sec80    =
3971*5113495bSYour Name 				report->noisefloor[chn_idx_lowest_enabled];
3972*5113495bSYour Name 			params.max_mag_sec80        = p_sfft->fft_peak_mag;
3973*5113495bSYour Name 			params.datalen = fft_hdr_length * 2;
3974*5113495bSYour Name 			params.datalen_sec80 = fft_hdr_length * 2;
3975*5113495bSYour Name 
3976*5113495bSYour Name 			marker = &spectral->rparams.marker[spectral_mode];
3977*5113495bSYour Name 			if (!marker->is_valid) {
3978*5113495bSYour Name 				/* update stats */
3979*5113495bSYour Name 				goto fail_no_print;
3980*5113495bSYour Name 			}
3981*5113495bSYour Name 			params.bin_pwr_data = temp +
3982*5113495bSYour Name 				marker->start_pri80 * fft_bin_size;
3983*5113495bSYour Name 			params.pwr_count = marker->num_pri80;
3984*5113495bSYour Name 			params.bin_pwr_data_sec80 = temp +
3985*5113495bSYour Name 				marker->start_sec80 * fft_bin_size;
3986*5113495bSYour Name 			params.pwr_count_sec80 = marker->num_sec80;
3987*5113495bSYour Name 			if (spectral->ch_width[spectral_mode] ==
3988*5113495bSYour Name 			    CH_WIDTH_80P80MHZ && wlan_psoc_nif_fw_ext_cap_get(
3989*5113495bSYour Name 			    psoc, WLAN_SOC_RESTRICTED_80P80_SUPPORT)) {
3990*5113495bSYour Name 				params.bin_pwr_data_5mhz = temp +
3991*5113495bSYour Name 					marker->start_5mhz * fft_bin_size;
3992*5113495bSYour Name 				params.pwr_count_5mhz = marker->num_5mhz;
3993*5113495bSYour Name 			}
3994*5113495bSYour Name 		} else {
3995*5113495bSYour Name 			params.bin_pwr_data = temp;
3996*5113495bSYour Name 			params.pwr_count = fft_bin_count;
3997*5113495bSYour Name 			params.datalen = (fft_hdr_length * 4);
3998*5113495bSYour Name 		}
3999*5113495bSYour Name 
4000*5113495bSYour Name 		/* Apply byte-swap on the FFT bins.
4001*5113495bSYour Name 		 * NOTE: Until this point, bytes of the FFT bins could be in
4002*5113495bSYour Name 		 *       reverse order on a big-endian machine. If the consumers
4003*5113495bSYour Name 		 *       of FFT bins expects bytes in the correct order,
4004*5113495bSYour Name 		 *       they should use them only after this point.
4005*5113495bSYour Name 		 */
4006*5113495bSYour Name 		if (p_sops->byte_swap_fft_bins) {
4007*5113495bSYour Name 			ret = p_sops->byte_swap_fft_bins(
4008*5113495bSYour Name 						&spectral->rparams,
4009*5113495bSYour Name 						temp, fft_bin_count);
4010*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret)) {
4011*5113495bSYour Name 				spectral_err_rl("Byte-swap on the FFT bins failed");
4012*5113495bSYour Name 				goto fail;
4013*5113495bSYour Name 			}
4014*5113495bSYour Name 		}
4015*5113495bSYour Name 
4016*5113495bSYour Name 		if (spectral_debug_level & (DEBUG_SPECTRAL2 | DEBUG_SPECTRAL4))
4017*5113495bSYour Name 			target_if_dump_fft_report_gen3(spectral, spectral_mode,
4018*5113495bSYour Name 						       p_fft_report, p_sfft);
4019*5113495bSYour Name 
4020*5113495bSYour Name 		target_if_spectral_verify_ts(spectral, report->data,
4021*5113495bSYour Name 					     params.tstamp);
4022*5113495bSYour Name 	} else if (is_secondaryseg_expected(spectral, spectral_mode)) {
4023*5113495bSYour Name 		/* RSSI is in 1/2 dBm steps, Convert it to dBm scale */
4024*5113495bSYour Name 		rssi = (sscan_report_fields.inband_pwr_db) >> 1;
4025*5113495bSYour Name 		params.agc_total_gain_sec80 =
4026*5113495bSYour Name 			sscan_report_fields.sscan_agc_total_gain;
4027*5113495bSYour Name 		params.gainchange_sec80 = sscan_report_fields.sscan_gainchange;
4028*5113495bSYour Name 		params.pri80ind_sec80 = sscan_report_fields.sscan_pri80;
4029*5113495bSYour Name 
4030*5113495bSYour Name 		/* Process Spectral search FFT report */
4031*5113495bSYour Name 		if (target_if_verify_sig_and_tag_gen3(
4032*5113495bSYour Name 				spectral, data,
4033*5113495bSYour Name 				TLV_TAG_SEARCH_FFT_REPORT_GEN3) != 0) {
4034*5113495bSYour Name 			spectral_err_rl("Unexpected tag/sig in sfft, detid= %u",
4035*5113495bSYour Name 					detector_id);
4036*5113495bSYour Name 			goto fail;
4037*5113495bSYour Name 		}
4038*5113495bSYour Name 		p_fft_report = (struct spectral_phyerr_fft_report_gen3 *)data;
4039*5113495bSYour Name 		fft_hdr_length = get_bitfield(
4040*5113495bSYour Name 				p_fft_report->fft_hdr_lts,
4041*5113495bSYour Name 				SPECTRAL_REPORT_LTS_HDR_LENGTH_SIZE_GEN3,
4042*5113495bSYour Name 				SPECTRAL_REPORT_LTS_HDR_LENGTH_POS_GEN3) * 4;
4043*5113495bSYour Name 		if (fft_hdr_length < 16) {
4044*5113495bSYour Name 			spectral_err("Wrong TLV length %u, detector id = %u",
4045*5113495bSYour Name 				     fft_hdr_length, detector_id);
4046*5113495bSYour Name 			goto fail;
4047*5113495bSYour Name 		}
4048*5113495bSYour Name 
4049*5113495bSYour Name 		report_len     = (fft_hdr_length + 8);
4050*5113495bSYour Name 
4051*5113495bSYour Name 		target_if_process_sfft_report_gen3(p_fft_report, p_sfft,
4052*5113495bSYour Name 						   &spectral->rparams);
4053*5113495bSYour Name 		/* It is expected to have same detector id for
4054*5113495bSYour Name 		 * summary and fft report
4055*5113495bSYour Name 		 */
4056*5113495bSYour Name 		if (detector_id != p_sfft->fft_detector_id) {
4057*5113495bSYour Name 			spectral_err_rl
4058*5113495bSYour Name 				("Different detid in ssummary(%u) and sfft(%u)",
4059*5113495bSYour Name 				 detector_id, p_sfft->fft_detector_id);
4060*5113495bSYour Name 			goto fail;
4061*5113495bSYour Name 		}
4062*5113495bSYour Name 
4063*5113495bSYour Name 		if (detector_id > spectral->rparams.num_spectral_detectors) {
4064*5113495bSYour Name 			spectral->diag_stats.spectral_invalid_detector_id++;
4065*5113495bSYour Name 			spectral_err("Invalid detector id %u, expected is 1",
4066*5113495bSYour Name 				     detector_id);
4067*5113495bSYour Name 			goto fail;
4068*5113495bSYour Name 		}
4069*5113495bSYour Name 		params.smode = spectral_mode;
4070*5113495bSYour Name 
4071*5113495bSYour Name 		fft_bin_count = target_if_spectral_get_bin_count_after_len_adj(
4072*5113495bSYour Name 			fft_hdr_length - spectral->rparams.fft_report_hdr_len,
4073*5113495bSYour Name 			spectral->params[spectral_mode].ss_rpt_mode,
4074*5113495bSYour Name 			&spectral->len_adj_swar, &fft_bin_size);
4075*5113495bSYour Name 		params.raw_timestamp_sec80 = p_sfft->timestamp;
4076*5113495bSYour Name 
4077*5113495bSYour Name 		/* Take care of state transitions for 160 MHz and 80p80 */
4078*5113495bSYour Name 		if (is_ch_width_160_or_80p80(spectral->ch_width
4079*5113495bSYour Name 		    [spectral_mode]) && spectral->rparams.
4080*5113495bSYour Name 		    fragmentation_160[spectral_mode]) {
4081*5113495bSYour Name 			ret = target_if_160mhz_delivery_state_change(
4082*5113495bSYour Name 					spectral, spectral_mode,
4083*5113495bSYour Name 					detector_id);
4084*5113495bSYour Name 			if (ret != QDF_STATUS_SUCCESS)
4085*5113495bSYour Name 				goto fail;
4086*5113495bSYour Name 		}
4087*5113495bSYour Name 
4088*5113495bSYour Name 		params.rssi_sec80 = rssi;
4089*5113495bSYour Name 
4090*5113495bSYour Name 		vdev = target_if_spectral_get_vdev(spectral, spectral_mode);
4091*5113495bSYour Name 		if (!vdev) {
4092*5113495bSYour Name 			spectral_info("First vdev is NULL");
4093*5113495bSYour Name 			reset_160mhz_delivery_state_machine
4094*5113495bSYour Name 						(spectral, spectral_mode);
4095*5113495bSYour Name 			return -EPERM;
4096*5113495bSYour Name 		}
4097*5113495bSYour Name 		vdev_rxchainmask = wlan_vdev_mlme_get_rxchainmask(vdev);
4098*5113495bSYour Name 		if (vdev_rxchainmask == 0) {
4099*5113495bSYour Name 			spectral_err("Vdev rxchainmask is zero.");
4100*5113495bSYour Name 			goto fail;
4101*5113495bSYour Name 		}
4102*5113495bSYour Name 		wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
4103*5113495bSYour Name 
4104*5113495bSYour Name 		chn_idx_lowest_enabled =
4105*5113495bSYour Name 		target_if_spectral_get_lowest_chn_idx(vdev_rxchainmask);
4106*5113495bSYour Name 		if (chn_idx_lowest_enabled >= DBR_MAX_CHAINS) {
4107*5113495bSYour Name 			spectral_err("Invalid chain index");
4108*5113495bSYour Name 			goto fail;
4109*5113495bSYour Name 		}
4110*5113495bSYour Name 
4111*5113495bSYour Name 		/* Need to change this as per FW team's inputs */
4112*5113495bSYour Name 		params.noise_floor_sec80    =
4113*5113495bSYour Name 			report->noisefloor[chn_idx_lowest_enabled];
4114*5113495bSYour Name 
4115*5113495bSYour Name 		params.max_mag_sec80        = p_sfft->fft_peak_mag;
4116*5113495bSYour Name 		/* params.max_index_sec80      = p_sfft->peak_inx; */
4117*5113495bSYour Name 		/* XXX Does this definition of datalen *still hold? */
4118*5113495bSYour Name 		params.datalen_sec80        = fft_hdr_length * 4;
4119*5113495bSYour Name 		params.pwr_count_sec80      = fft_bin_count;
4120*5113495bSYour Name 		params.bin_pwr_data_sec80   =
4121*5113495bSYour Name 			(uint8_t *)((uint8_t *)p_fft_report +
4122*5113495bSYour Name 			 SPECTRAL_FFT_BINS_POS);
4123*5113495bSYour Name 
4124*5113495bSYour Name 		/* Apply byte-swap on the FFT bins.
4125*5113495bSYour Name 		 * NOTE: Until this point, bytes of the FFT bins could be in
4126*5113495bSYour Name 		 *       reverse order on a big-endian machine. If the consumers
4127*5113495bSYour Name 		 *       of FFT bins expects bytes in the correct order,
4128*5113495bSYour Name 		 *       they should use them only after this point.
4129*5113495bSYour Name 		 */
4130*5113495bSYour Name 		if (p_sops->byte_swap_fft_bins) {
4131*5113495bSYour Name 			ret = p_sops->byte_swap_fft_bins(
4132*5113495bSYour Name 					&spectral->rparams,
4133*5113495bSYour Name 					params.bin_pwr_data_sec80,
4134*5113495bSYour Name 					fft_bin_count);
4135*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret)) {
4136*5113495bSYour Name 				spectral_err_rl("Byte-swap on the FFT bins failed");
4137*5113495bSYour Name 				goto fail;
4138*5113495bSYour Name 			}
4139*5113495bSYour Name 		}
4140*5113495bSYour Name 
4141*5113495bSYour Name 		if (spectral_debug_level & (DEBUG_SPECTRAL2 | DEBUG_SPECTRAL4))
4142*5113495bSYour Name 			target_if_dump_fft_report_gen3(spectral, spectral_mode,
4143*5113495bSYour Name 						       p_fft_report, p_sfft);
4144*5113495bSYour Name 
4145*5113495bSYour Name 	} else {
4146*5113495bSYour Name 		spectral_err("Spectral state machine in undefined state");
4147*5113495bSYour Name 		goto fail;
4148*5113495bSYour Name 	}
4149*5113495bSYour Name 
4150*5113495bSYour Name 	target_if_spectral_check_buffer_poisoning(spectral, report,
4151*5113495bSYour Name 						  fft_bin_count, spectral_mode);
4152*5113495bSYour Name 	qdf_mem_copy(&params.classifier_params,
4153*5113495bSYour Name 		     &spectral->classifier_params,
4154*5113495bSYour Name 		     sizeof(struct spectral_classifier_params));
4155*5113495bSYour Name 
4156*5113495bSYour Name 	target_if_spectral_log_SAMP_param(&params);
4157*5113495bSYour Name 	target_if_spectral_create_samp_msg(spectral, &params);
4158*5113495bSYour Name 
4159*5113495bSYour Name 	return 0;
4160*5113495bSYour Name  fail:
4161*5113495bSYour Name 	spectral_err_rl("Error while processing Spectral report");
4162*5113495bSYour Name fail_no_print:
4163*5113495bSYour Name 	if (spectral_mode != SPECTRAL_SCAN_MODE_INVALID)
4164*5113495bSYour Name 		reset_160mhz_delivery_state_machine(spectral, spectral_mode);
4165*5113495bSYour Name 	return -EPERM;
4166*5113495bSYour Name }
4167*5113495bSYour Name #endif /* OPTIMIZED_SAMP_MESSAGE */
4168*5113495bSYour Name 
target_if_spectral_process_report_gen3(struct wlan_objmgr_pdev * pdev,void * buf)4169*5113495bSYour Name int target_if_spectral_process_report_gen3(
4170*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev,
4171*5113495bSYour Name 	void *buf)
4172*5113495bSYour Name {
4173*5113495bSYour Name 	int ret = 0;
4174*5113495bSYour Name 	struct direct_buf_rx_data *payload = buf;
4175*5113495bSYour Name 	struct target_if_spectral *spectral;
4176*5113495bSYour Name 	struct spectral_report report = {0};
4177*5113495bSYour Name 	int samp_msg_index;
4178*5113495bSYour Name 	struct spectral_data_stats *spectral_dp_stats;
4179*5113495bSYour Name 
4180*5113495bSYour Name 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
4181*5113495bSYour Name 	if (!spectral) {
4182*5113495bSYour Name 		spectral_err("Spectral target object is null");
4183*5113495bSYour Name 		return -EINVAL;
4184*5113495bSYour Name 	}
4185*5113495bSYour Name 
4186*5113495bSYour Name 	spectral_dp_stats = &spectral->data_stats;
4187*5113495bSYour Name 	spectral_dp_stats->spectral_rx_events++;
4188*5113495bSYour Name 
4189*5113495bSYour Name 	report.data = payload->vaddr;
4190*5113495bSYour Name 	if (payload->meta_data_valid) {
4191*5113495bSYour Name 		qdf_mem_copy(report.noisefloor, payload->meta_data.noisefloor,
4192*5113495bSYour Name 			     qdf_min(sizeof(report.noisefloor),
4193*5113495bSYour Name 				     sizeof(payload->meta_data.noisefloor)));
4194*5113495bSYour Name 		report.reset_delay = payload->meta_data.reset_delay;
4195*5113495bSYour Name 		report.cfreq1 = payload->meta_data.cfreq1;
4196*5113495bSYour Name 		report.cfreq2 = payload->meta_data.cfreq2;
4197*5113495bSYour Name 		report.ch_width = payload->meta_data.ch_width;
4198*5113495bSYour Name 	}
4199*5113495bSYour Name 
4200*5113495bSYour Name 	if (spectral_debug_level & (DEBUG_SPECTRAL2 | DEBUG_SPECTRAL4)) {
4201*5113495bSYour Name 		spectral_debug("Printing the spectral phyerr buffer for debug");
4202*5113495bSYour Name 		spectral_debug("Datalength of buffer = 0x%zx(%zd) bufptr = 0x%pK",
4203*5113495bSYour Name 			       payload->dbr_len,
4204*5113495bSYour Name 			       payload->dbr_len,
4205*5113495bSYour Name 			       payload->vaddr);
4206*5113495bSYour Name 		target_if_spectral_hexdump((unsigned char *)payload->vaddr,
4207*5113495bSYour Name 					   1024);
4208*5113495bSYour Name 	}
4209*5113495bSYour Name 
4210*5113495bSYour Name 	samp_msg_index = spectral->spectral_sent_msg;
4211*5113495bSYour Name 
4212*5113495bSYour Name 	ret = target_if_consume_spectral_report_gen3(spectral, &report);
4213*5113495bSYour Name 
4214*5113495bSYour Name 	/* Reset debug level when SAMP msg is sent successfully or on error */
4215*5113495bSYour Name 	if ((spectral_debug_level & DEBUG_SPECTRAL4) &&
4216*5113495bSYour Name 	    (ret != 0 || spectral->spectral_sent_msg == samp_msg_index + 1))
4217*5113495bSYour Name 		spectral_debug_level = DEBUG_SPECTRAL;
4218*5113495bSYour Name 
4219*5113495bSYour Name 	return ret;
4220*5113495bSYour Name }
4221*5113495bSYour Name #else
target_if_spectral_process_report_gen3(struct wlan_objmgr_pdev * pdev,void * buf)4222*5113495bSYour Name int target_if_spectral_process_report_gen3(
4223*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev,
4224*5113495bSYour Name 	void *buf)
4225*5113495bSYour Name {
4226*5113495bSYour Name 	spectral_err("Direct dma support is not enabled");
4227*5113495bSYour Name 	return -EINVAL;
4228*5113495bSYour Name }
4229*5113495bSYour Name #endif
4230*5113495bSYour Name qdf_export_symbol(target_if_spectral_process_report_gen3);
4231*5113495bSYour Name /* END of spectral GEN III HW specific functions */
4232*5113495bSYour Name 
4233*5113495bSYour Name #endif  /* WLAN_CONV_SPECTRAL_ENABLE */
4234