xref: /wlan-dirver/qca-wifi-host-cmn/target_if/spectral/target_if_spectral_phyerr.c (revision a86b23ee68a2491aede2e03991f3fb37046f4e41)
1 /*
2  * Copyright (c) 2011,2017-2020 The Linux Foundation. All rights reserved.
3  *
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <osdep.h>
21 #include <qdf_types.h>
22 #include <qdf_module.h>
23 #include <wlan_tgt_def_config.h>
24 #include <hif.h>
25 #include <hif_hw_version.h>
26 #include <wmi_unified_api.h>
27 #include <target_if_spectral.h>
28 #include <wlan_lmac_if_def.h>
29 #include <wlan_osif_priv.h>
30 #include <reg_services_public_struct.h>
31 #include <target_if.h>
32 #ifdef DIRECT_BUF_RX_ENABLE
33 #include <target_if_direct_buf_rx_api.h>
34 #endif
35 extern int spectral_debug_level;
36 
37 #ifdef WLAN_CONV_SPECTRAL_ENABLE
38 
39 #define SPECTRAL_HEXDUMP_OCTET_PRINT_SIZE           (3)
40 #define SPECTRAL_HEXDUMP_NUM_OCTETS_PER_LINE        (16)
41 #define SPECTRAL_HEXDUMP_EXTRA_BUFFER_PER_LINE      (16)
42 
43 /*
44  * Provision for the expected hexdump line size as follows:
45  *
46  * Size per octet multiplied by number of octets per line
47  * +
48  * ASCII representation which is equivalent in print size to number of octets
49  * per line
50  * +
51  * Some extra buffer
52  */
53 #define SPECTRAL_HEXDUMP_LINESIZE                           \
54 		((SPECTRAL_HEXDUMP_OCTET_PRINT_SIZE *       \
55 		  SPECTRAL_HEXDUMP_NUM_OCTETS_PER_LINE) +   \
56 		 SPECTRAL_HEXDUMP_NUM_OCTETS_PER_LINE +     \
57 		 SPECTRAL_HEXDUMP_EXTRA_BUFFER_PER_LINE)
58 
59 /**
60  * target_if_spectral_hexdump() - Print hexdump of the given buffer
61  * @_buf: Pointer to buffer
62  * @_len: Length of the buffer
63  *
64  * Print the hexdump of buffer upto given length. Print upto
65  * SPECTRAL_HEXDUMP_NUM_OCTETS_PER_LINE per line, followed by the ASCII
66  * representation of these octets.
67  */
68 static inline void target_if_spectral_hexdump(unsigned char *_buf, int _len)
69 {
70 	int i, mod;
71 	unsigned char ascii[SPECTRAL_HEXDUMP_NUM_OCTETS_PER_LINE + 1];
72 	unsigned char *pc = (_buf);
73 	char hexdump_line[SPECTRAL_HEXDUMP_LINESIZE + 1];
74 	int loc = 0;
75 
76 	qdf_mem_zero(hexdump_line, sizeof(hexdump_line));
77 
78 	if (_len <= 0) {
79 		spectral_err("buffer len is %d, too short", _len);
80 		return;
81 	}
82 
83 	for (i = 0; i < _len; i++) {
84 		mod = i % SPECTRAL_HEXDUMP_NUM_OCTETS_PER_LINE;
85 
86 		if (!mod) {
87 			if (i) {
88 				qdf_assert_always(loc < sizeof(hexdump_line));
89 				loc += snprintf(&hexdump_line[loc],
90 						sizeof(hexdump_line) - loc,
91 						"  %s", ascii);
92 				spectral_debug("%s", hexdump_line);
93 				qdf_mem_zero(hexdump_line,
94 					     sizeof(hexdump_line));
95 				loc = 0;
96 			}
97 		}
98 
99 		qdf_assert_always(loc < sizeof(hexdump_line));
100 		loc += snprintf(&hexdump_line[loc], sizeof(hexdump_line) - loc,
101 				" %02x", pc[i]);
102 
103 		if ((pc[i] < 0x20) || (pc[i] > 0x7e))
104 			ascii[mod] = '.';
105 		else
106 			ascii[mod] = pc[i];
107 		ascii[(mod) + 1] = '\0';
108 	}
109 
110 	while ((i % SPECTRAL_HEXDUMP_NUM_OCTETS_PER_LINE) != 0) {
111 		qdf_assert_always(loc < sizeof(hexdump_line));
112 		loc += snprintf(&hexdump_line[loc], sizeof(hexdump_line) - loc,
113 				"   ");
114 		i++;
115 	}
116 
117 	qdf_assert_always(loc < sizeof(hexdump_line));
118 	snprintf(&hexdump_line[loc], sizeof(hexdump_line) - loc, "  %s", ascii);
119 	spectral_debug("%s", hexdump_line);
120 }
121 
122 /**
123  * target_if_print_buf() - Prints given buffer for given length
124  * @pbuf: Pointer to buffer
125  * @len: length
126  *
127  * Prints given buffer for given length
128  *
129  * Return: void
130  */
131 static void
132 target_if_print_buf(uint8_t *pbuf, int len)
133 {
134 	int i = 0;
135 
136 	for (i = 0; i < len; i++) {
137 		spectral_debug("%02X ", pbuf[i]);
138 		if (i % 32 == 31)
139 			spectral_debug("\n");
140 	}
141 }
142 
143 int
144 target_if_spectral_dump_fft(uint8_t *pfft, int fftlen)
145 {
146 	int i = 0;
147 
148 	/*
149 	 * TODO : Do not delete the following print
150 	 *        The scripts used to validate Spectral depend on this Print
151 	 */
152 	spectral_debug("SPECTRAL : FFT Length is 0x%x (%d)", fftlen, fftlen);
153 
154 	spectral_debug("fft_data # ");
155 	for (i = 0; i < fftlen; i++)
156 		spectral_debug("%d ", pfft[i]);
157 	spectral_debug("\n");
158 	return 0;
159 }
160 
161 QDF_STATUS target_if_spectral_fw_hang(struct target_if_spectral *spectral)
162 {
163 	struct crash_inject param;
164 	struct wlan_objmgr_pdev *pdev;
165 	struct wlan_objmgr_psoc *psoc;
166 	struct target_if_psoc_spectral *psoc_spectral;
167 
168 	if (!spectral) {
169 		spectral_err("Spectral LMAC object is null");
170 		return QDF_STATUS_E_INVAL;
171 	}
172 
173 	pdev = spectral->pdev_obj;
174 	if (!pdev) {
175 		spectral_err("pdev is null");
176 		return QDF_STATUS_E_FAILURE;
177 	}
178 
179 	psoc = wlan_pdev_get_psoc(pdev);
180 	if (!psoc) {
181 		spectral_err("psoc is null");
182 		return QDF_STATUS_E_FAILURE;
183 	}
184 
185 	psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
186 	if (!psoc_spectral) {
187 		spectral_err("spectral psoc object is null");
188 		return QDF_STATUS_E_FAILURE;
189 	}
190 
191 	qdf_mem_set(&param, sizeof(param), 0);
192 	param.type = 1; //RECOVERY_SIM_ASSERT
193 
194 	return psoc_spectral->wmi_ops.wmi_spectral_crash_inject(
195 		GET_WMI_HDL_FROM_PDEV(spectral->pdev_obj), &param);
196 }
197 
198 void
199 target_if_dbg_print_samp_param(struct target_if_samp_msg_params *p)
200 {
201 	spectral_debug("\nSAMP Packet : -------------------- START --------------------");
202 	spectral_debug("Freq        = %d", p->freq);
203 	spectral_debug("RSSI        = %d", p->rssi);
204 	spectral_debug("Bin Count   = %d", p->pwr_count);
205 	spectral_debug("Timestamp   = %d", p->tstamp);
206 	spectral_debug("SAMP Packet : -------------------- END -----------------------");
207 }
208 
209 void
210 target_if_dbg_print_samp_msg(struct spectral_samp_msg *ss_msg)
211 {
212 	int i = 0;
213 
214 	struct spectral_samp_data *p = &ss_msg->samp_data;
215 	struct spectral_classifier_params *pc = &p->classifier_params;
216 	struct interf_src_rsp *pi = &p->interf_list;
217 
218 	spectral_dbg_line();
219 	spectral_debug("Spectral Message");
220 	spectral_dbg_line();
221 	spectral_debug("Signature   :   0x%x", ss_msg->signature);
222 	spectral_debug("Freq        :   %d", ss_msg->freq);
223 	spectral_debug("Freq load   :   %d", ss_msg->freq_loading);
224 	spectral_debug("Intfnc type :   %d", ss_msg->int_type);
225 	spectral_dbg_line();
226 	spectral_debug("Spectral Data info");
227 	spectral_dbg_line();
228 	spectral_debug("data length     :   %d", p->spectral_data_len);
229 	spectral_debug("rssi            :   %d", p->spectral_rssi);
230 	spectral_debug("combined rssi   :   %d", p->spectral_combined_rssi);
231 	spectral_debug("upper rssi      :   %d", p->spectral_upper_rssi);
232 	spectral_debug("lower rssi      :   %d", p->spectral_lower_rssi);
233 	spectral_debug("bw info         :   %d", p->spectral_bwinfo);
234 	spectral_debug("timestamp       :   %d", p->spectral_tstamp);
235 	spectral_debug("max index       :   %d", p->spectral_max_index);
236 	spectral_debug("max exp         :   %d", p->spectral_max_exp);
237 	spectral_debug("max mag         :   %d", p->spectral_max_mag);
238 	spectral_debug("last timstamp   :   %d", p->spectral_last_tstamp);
239 	spectral_debug("upper max idx   :   %d", p->spectral_upper_max_index);
240 	spectral_debug("lower max idx   :   %d", p->spectral_lower_max_index);
241 	spectral_debug("bin power count :   %d", p->bin_pwr_count);
242 	spectral_dbg_line();
243 	spectral_debug("Classifier info");
244 	spectral_dbg_line();
245 	spectral_debug("20/40 Mode      :   %d", pc->spectral_20_40_mode);
246 	spectral_debug("dc index        :   %d", pc->spectral_dc_index);
247 	spectral_debug("dc in MHz       :   %d", pc->spectral_dc_in_mhz);
248 	spectral_debug("upper channel   :   %d", pc->upper_chan_in_mhz);
249 	spectral_debug("lower channel   :   %d", pc->lower_chan_in_mhz);
250 	spectral_dbg_line();
251 	spectral_debug("Interference info");
252 	spectral_dbg_line();
253 	spectral_debug("inter count     :   %d", pi->count);
254 
255 	for (i = 0; i < pi->count; i++) {
256 		spectral_debug("inter type  :   %d",
257 			       pi->interf[i].interf_type);
258 		spectral_debug("min freq    :   %d",
259 			       pi->interf[i].interf_min_freq);
260 		spectral_debug("max freq    :   %d",
261 			       pi->interf[i].interf_max_freq);
262 	}
263 }
264 
265 uint32_t
266 target_if_get_offset_swar_sec80(uint32_t channel_width)
267 {
268 	uint32_t offset = 0;
269 
270 	switch (channel_width) {
271 	case CH_WIDTH_20MHZ:
272 		offset = OFFSET_CH_WIDTH_20;
273 		break;
274 	case CH_WIDTH_40MHZ:
275 		offset = OFFSET_CH_WIDTH_40;
276 		break;
277 	case CH_WIDTH_80MHZ:
278 		offset = OFFSET_CH_WIDTH_80;
279 		break;
280 	case CH_WIDTH_160MHZ:
281 	case CH_WIDTH_80P80MHZ:
282 		offset = OFFSET_CH_WIDTH_160;
283 		break;
284 	default:
285 		offset = OFFSET_CH_WIDTH_80;
286 		break;
287 	}
288 	return offset;
289 }
290 
291 /**
292  * target_if_dump_summary_report_gen2() - Dump Spectral Summary Report for gen2
293  * @ptlv: Pointer to Spectral Phyerr TLV
294  * @tlvlen: length
295  * @is_160_format: Indicates whether information provided by HW is in altered
296  *                 format for 802.11ac 160/80+80 MHz support (QCA9984 onwards)
297  *
298  * Dump Spectral Summary Report for gen2
299  *
300  * Return: Success/Failure
301  */
302 static int
303 target_if_dump_summary_report_gen2(struct spectral_phyerr_tlv_gen2 *ptlv,
304 				   int tlvlen, bool is_160_format)
305 {
306 	/*
307 	 * For simplicity, everything is defined as uint32_t (except one).
308 	 * Proper code will later use the right sizes.
309 	 */
310 
311 	/*
312 	 * For easy comparision between MDK team and OS team, the MDK script
313 	 * variable names have been used
314 	 */
315 
316 	uint32_t agc_mb_gain;
317 	uint32_t sscan_gidx;
318 	uint32_t agc_total_gain;
319 	uint32_t recent_rfsat;
320 	uint32_t ob_flag;
321 	uint32_t nb_mask;
322 	uint32_t peak_mag;
323 	int16_t peak_inx;
324 
325 	uint32_t ss_summary_A = 0;
326 	uint32_t ss_summary_B = 0;
327 	uint32_t ss_summary_C = 0;
328 	uint32_t ss_summary_D = 0;
329 	uint32_t ss_summary_E = 0;
330 	struct spectral_phyerr_hdr_gen2 *phdr =
331 	    (struct spectral_phyerr_hdr_gen2 *)(
332 		(uint8_t *)ptlv +
333 		sizeof(struct spectral_phyerr_tlv_gen2));
334 
335 	spectral_debug("SPECTRAL : SPECTRAL SUMMARY REPORT");
336 
337 	if (is_160_format) {
338 		if (tlvlen != 20) {
339 			spectral_err("Unexpected TLV length %d for Spectral Summary Report! Hexdump follows",
340 				     tlvlen);
341 			target_if_print_buf((uint8_t *)ptlv, tlvlen + 4);
342 			return -EPERM;
343 		}
344 
345 		/* Doing copy as the contents may not be aligned */
346 		qdf_mem_copy(&ss_summary_A, (uint8_t *)phdr, sizeof(int));
347 		qdf_mem_copy(&ss_summary_B,
348 			     (uint8_t *)((uint8_t *)phdr + sizeof(int)),
349 			     sizeof(int));
350 		qdf_mem_copy(&ss_summary_C,
351 			     (uint8_t *)((uint8_t *)phdr + 2 * sizeof(int)),
352 			     sizeof(int));
353 		qdf_mem_copy(&ss_summary_D,
354 			     (uint8_t *)((uint8_t *)phdr + 3 * sizeof(int)),
355 			     sizeof(int));
356 		qdf_mem_copy(&ss_summary_E,
357 			     (uint8_t *)((uint8_t *)phdr + 4 * sizeof(int)),
358 			     sizeof(int));
359 
360 		/*
361 		 * The following is adapted from MDK scripts for
362 		 * easier comparability
363 		 */
364 
365 		recent_rfsat = ((ss_summary_A >> 8) & 0x1);
366 		sscan_gidx = (ss_summary_A & 0xff);
367 		spectral_debug("sscan_gidx=%d, is_recent_rfsat=%d",
368 			       sscan_gidx, recent_rfsat);
369 
370 		/* First segment */
371 		agc_mb_gain = ((ss_summary_B >> 10) & 0x7f);
372 		agc_total_gain = (ss_summary_B & 0x3ff);
373 		nb_mask = ((ss_summary_C >> 22) & 0xff);
374 		ob_flag = ((ss_summary_B >> 17) & 0x1);
375 		peak_inx = (ss_summary_C & 0xfff);
376 		if (peak_inx > 2047)
377 			peak_inx = peak_inx - 4096;
378 		peak_mag = ((ss_summary_C >> 12) & 0x3ff);
379 
380 		spectral_debug("agc_total_gain_segid0 = 0x%.2x, agc_mb_gain_segid0=%d",
381 			       agc_total_gain, agc_mb_gain);
382 		spectral_debug("nb_mask_segid0 = 0x%.2x, ob_flag_segid0=%d, peak_index_segid0=%d, peak_mag_segid0=%d",
383 			       nb_mask, ob_flag, peak_inx, peak_mag);
384 
385 		/* Second segment */
386 		agc_mb_gain = ((ss_summary_D >> 10) & 0x7f);
387 		agc_total_gain = (ss_summary_D & 0x3ff);
388 		nb_mask = ((ss_summary_E >> 22) & 0xff);
389 		ob_flag = ((ss_summary_D >> 17) & 0x1);
390 		peak_inx = (ss_summary_E & 0xfff);
391 		if (peak_inx > 2047)
392 			peak_inx = peak_inx - 4096;
393 		peak_mag = ((ss_summary_E >> 12) & 0x3ff);
394 
395 		spectral_debug("agc_total_gain_segid1 = 0x%.2x, agc_mb_gain_segid1=%d",
396 			       agc_total_gain, agc_mb_gain);
397 		spectral_debug("nb_mask_segid1 = 0x%.2x, ob_flag_segid1=%d, peak_index_segid1=%d, peak_mag_segid1=%d",
398 			       nb_mask, ob_flag, peak_inx, peak_mag);
399 	} else {
400 		if (tlvlen != 8) {
401 			spectral_err("Unexpected TLV length %d for Spectral Summary Report! Hexdump follows",
402 				     tlvlen);
403 			target_if_print_buf((uint8_t *)ptlv, tlvlen + 4);
404 			return -EPERM;
405 		}
406 
407 		/* Doing copy as the contents may not be aligned */
408 		qdf_mem_copy(&ss_summary_A, (uint8_t *)phdr, sizeof(int));
409 		qdf_mem_copy(&ss_summary_B,
410 			     (uint8_t *)((uint8_t *)phdr + sizeof(int)),
411 			     sizeof(int));
412 
413 		nb_mask = ((ss_summary_B >> 22) & 0xff);
414 		ob_flag = ((ss_summary_B >> 30) & 0x1);
415 		peak_inx = (ss_summary_B & 0xfff);
416 
417 		if (peak_inx > 2047)
418 			peak_inx = peak_inx - 4096;
419 
420 		peak_mag = ((ss_summary_B >> 12) & 0x3ff);
421 		agc_mb_gain = ((ss_summary_A >> 24) & 0x7f);
422 		agc_total_gain = (ss_summary_A & 0x3ff);
423 		sscan_gidx = ((ss_summary_A >> 16) & 0xff);
424 		recent_rfsat = ((ss_summary_B >> 31) & 0x1);
425 
426 		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",
427 			       nb_mask, ob_flag, peak_inx, peak_mag,
428 			       agc_mb_gain, agc_total_gain, sscan_gidx,
429 			       recent_rfsat);
430 	}
431 
432 	return 0;
433 }
434 
435 /**
436  * target_if_process_sfft_report_gen2() - Process Search FFT Report
437  * @ptlv: Pointer to Spectral Phyerr TLV
438  * @tlvlen: length
439  * @p_fft_info: Pointer to search fft info
440  *
441  * Dump Spectral Summary Report for gen2
442  *
443  * Return: Success/Failure
444  */
445 static int
446 target_if_process_sfft_report_gen2(
447 	struct spectral_phyerr_tlv_gen2 *ptlv,
448 	int tlvlen,
449 	struct spectral_search_fft_info_gen2 *p_fft_info)
450 {
451 	/*
452 	 * For simplicity, everything is defined as uint32_t (except one).
453 	 * Proper code will later use the right sizes.
454 	 */
455 	/*
456 	 * For easy comparision between MDK team and OS team, the MDK script
457 	 * variable names have been used
458 	 */
459 	uint32_t relpwr_db;
460 	uint32_t num_str_bins_ib;
461 	uint32_t base_pwr;
462 	uint32_t total_gain_info;
463 
464 	uint32_t fft_chn_idx;
465 	int16_t peak_inx;
466 	uint32_t avgpwr_db;
467 	uint32_t peak_mag;
468 
469 	uint32_t fft_summary_A = 0;
470 	uint32_t fft_summary_B = 0;
471 	uint8_t *tmp = (uint8_t *)ptlv;
472 	struct spectral_phyerr_hdr_gen2 *phdr =
473 	    (struct spectral_phyerr_hdr_gen2 *)(
474 		tmp +
475 		sizeof(struct spectral_phyerr_tlv_gen2));
476 
477 	/* Relook this */
478 	if (tlvlen < 8) {
479 		spectral_err("Unexpected TLV length %d for Spectral Summary Report! Hexdump follows",
480 			     tlvlen);
481 		target_if_print_buf((uint8_t *)ptlv, tlvlen + 4);
482 		return -EPERM;
483 	}
484 
485 	/* Doing copy as the contents may not be aligned */
486 	qdf_mem_copy(&fft_summary_A, (uint8_t *)phdr, sizeof(int));
487 	qdf_mem_copy(&fft_summary_B,
488 		     (uint8_t *)((uint8_t *)phdr + sizeof(int)),
489 		     sizeof(int));
490 
491 	relpwr_db = ((fft_summary_B >> 26) & 0x3f);
492 	num_str_bins_ib = fft_summary_B & 0xff;
493 	base_pwr = ((fft_summary_A >> 14) & 0x1ff);
494 	total_gain_info = ((fft_summary_A >> 23) & 0x1ff);
495 
496 	fft_chn_idx = ((fft_summary_A >> 12) & 0x3);
497 	peak_inx = fft_summary_A & 0xfff;
498 
499 	if (peak_inx > 2047)
500 		peak_inx = peak_inx - 4096;
501 
502 	avgpwr_db = ((fft_summary_B >> 18) & 0xff);
503 	peak_mag = ((fft_summary_B >> 8) & 0x3ff);
504 
505 	/* Populate the Search FFT Info */
506 	if (p_fft_info) {
507 		p_fft_info->relpwr_db = relpwr_db;
508 		p_fft_info->num_str_bins_ib = num_str_bins_ib;
509 		p_fft_info->base_pwr = base_pwr;
510 		p_fft_info->total_gain_info = total_gain_info;
511 		p_fft_info->fft_chn_idx = fft_chn_idx;
512 		p_fft_info->peak_inx = peak_inx;
513 		p_fft_info->avgpwr_db = avgpwr_db;
514 		p_fft_info->peak_mag = peak_mag;
515 	}
516 
517 	return 0;
518 }
519 
520 /**
521  * target_if_dump_adc_report_gen2() - Dump ADC Reports for gen2
522  * @ptlv: Pointer to Spectral Phyerr TLV
523  * @tlvlen: length
524  *
525  * Dump ADC Reports for gen2
526  *
527  * Return: Success/Failure
528  */
529 static int
530 target_if_dump_adc_report_gen2(
531 	struct spectral_phyerr_tlv_gen2 *ptlv, int tlvlen)
532 {
533 	int i;
534 	uint32_t *pdata;
535 	uint32_t data;
536 
537 	/*
538 	 * For simplicity, everything is defined as uint32_t (except one).
539 	 * Proper code will later use the right sizes.
540 	 */
541 	uint32_t samp_fmt;
542 	uint32_t chn_idx;
543 	uint32_t recent_rfsat;
544 	uint32_t agc_mb_gain;
545 	uint32_t agc_total_gain;
546 
547 	uint32_t adc_summary = 0;
548 
549 	uint8_t *ptmp = (uint8_t *)ptlv;
550 
551 	spectral_debug("SPECTRAL : ADC REPORT");
552 
553 	/* Relook this */
554 	if (tlvlen < 4) {
555 		spectral_err("Unexpected TLV length %d for ADC Report! Hexdump follows",
556 			     tlvlen);
557 		target_if_print_buf((uint8_t *)ptlv, tlvlen + 4);
558 		return -EPERM;
559 	}
560 
561 	qdf_mem_copy(&adc_summary, (uint8_t *)(ptlv + 4), sizeof(int));
562 
563 	samp_fmt = ((adc_summary >> 28) & 0x1);
564 	chn_idx = ((adc_summary >> 24) & 0x3);
565 	recent_rfsat = ((adc_summary >> 23) & 0x1);
566 	agc_mb_gain = ((adc_summary >> 16) & 0x7f);
567 	agc_total_gain = adc_summary & 0x3ff;
568 
569 	spectral_debug("samp_fmt= %u, chn_idx= %u, recent_rfsat= %u, agc_mb_gain=%u agc_total_gain=%u",
570 		       samp_fmt, chn_idx, recent_rfsat, agc_mb_gain,
571 		       agc_total_gain);
572 
573 	for (i = 0; i < (tlvlen / 4); i++) {
574 		pdata = (uint32_t *)(ptmp + 4 + i * 4);
575 		data = *pdata;
576 
577 		/* Interpreting capture format 1 */
578 		if (1) {
579 			uint8_t i1;
580 			uint8_t q1;
581 			uint8_t i2;
582 			uint8_t q2;
583 			int8_t si1;
584 			int8_t sq1;
585 			int8_t si2;
586 			int8_t sq2;
587 
588 			i1 = data & 0xff;
589 			q1 = (data >> 8) & 0xff;
590 			i2 = (data >> 16) & 0xff;
591 			q2 = (data >> 24) & 0xff;
592 
593 			if (i1 > 127)
594 				si1 = i1 - 256;
595 			else
596 				si1 = i1;
597 
598 			if (q1 > 127)
599 				sq1 = q1 - 256;
600 			else
601 				sq1 = q1;
602 
603 			if (i2 > 127)
604 				si2 = i2 - 256;
605 			else
606 				si2 = i2;
607 
608 			if (q2 > 127)
609 				sq2 = q2 - 256;
610 			else
611 				sq2 = q2;
612 
613 			spectral_debug("SPECTRAL ADC : Interpreting capture format 1");
614 			spectral_debug("adc_data_format_1 # %d %d %d",
615 				       2 * i, si1, sq1);
616 			spectral_debug("adc_data_format_1 # %d %d %d",
617 				       2 * i + 1, si2, sq2);
618 		}
619 
620 		/* Interpreting capture format 0 */
621 		if (1) {
622 			uint16_t i1;
623 			uint16_t q1;
624 			int16_t si1;
625 			int16_t sq1;
626 
627 			i1 = data & 0xffff;
628 			q1 = (data >> 16) & 0xffff;
629 			if (i1 > 32767)
630 				si1 = i1 - 65536;
631 			else
632 				si1 = i1;
633 
634 			if (q1 > 32767)
635 				sq1 = q1 - 65536;
636 			else
637 				sq1 = q1;
638 			spectral_debug("SPECTRAL ADC : Interpreting capture format 0");
639 			spectral_debug("adc_data_format_2 # %d %d %d",
640 				       i, si1, sq1);
641 		}
642 	}
643 
644 	spectral_debug("\n");
645 
646 	return 0;
647 }
648 
649 /**
650  * target_if_dump_sfft_report_gen2() - Process Search FFT Report for gen2
651  * @ptlv: Pointer to Spectral Phyerr TLV
652  * @tlvlen: length
653  * @is_160_format: Indicates 160 format
654  *
655  * Process Search FFT Report for gen2
656  *
657  * Return: Success/Failure
658  */
659 static int
660 target_if_dump_sfft_report_gen2(struct spectral_phyerr_tlv_gen2 *ptlv,
661 				int tlvlen, bool is_160_format)
662 {
663 	int i;
664 	uint32_t fft_mag;
665 
666 	/*
667 	 * For simplicity, everything is defined as uint32_t (except one).
668 	 * Proper code will later use the right sizes.
669 	 */
670 	/*
671 	 * For easy comparision between MDK team and OS team, the MDK script
672 	 * variable names have been used
673 	 */
674 	uint32_t relpwr_db;
675 	uint32_t num_str_bins_ib;
676 	uint32_t base_pwr;
677 	uint32_t total_gain_info;
678 
679 	uint32_t fft_chn_idx;
680 	int16_t peak_inx;
681 	uint32_t avgpwr_db;
682 	uint32_t peak_mag;
683 	uint8_t segid;
684 
685 	uint32_t fft_summary_A = 0;
686 	uint32_t fft_summary_B = 0;
687 	uint32_t fft_summary_C = 0;
688 	uint8_t *tmp = (uint8_t *)ptlv;
689 	struct spectral_phyerr_hdr_gen2 *phdr =
690 	    (struct spectral_phyerr_hdr_gen2 *)(
691 		tmp +
692 		sizeof(struct spectral_phyerr_tlv_gen2));
693 	uint32_t segid_skiplen = 0;
694 
695 	if (is_160_format)
696 		segid_skiplen = sizeof(SPECTRAL_SEGID_INFO);
697 
698 	spectral_debug("SPECTRAL : SEARCH FFT REPORT");
699 
700 	/* Relook this */
701 	if (tlvlen < (8 + segid_skiplen)) {
702 		spectral_err("Unexpected TLV length %d for Spectral Summary Report! Hexdump follows",
703 			     tlvlen);
704 		target_if_print_buf((uint8_t *)ptlv, tlvlen + 4);
705 		return -EPERM;
706 	}
707 
708 	/* Doing copy as the contents may not be aligned */
709 	qdf_mem_copy(&fft_summary_A, (uint8_t *)phdr, sizeof(int));
710 	qdf_mem_copy(&fft_summary_B,
711 		     (uint8_t *)((uint8_t *)phdr + sizeof(int)),
712 		     sizeof(int));
713 	if (is_160_format)
714 		qdf_mem_copy(&fft_summary_C,
715 			     (uint8_t *)((uint8_t *)phdr + 2 * sizeof(int)),
716 			     sizeof(int));
717 
718 	relpwr_db = ((fft_summary_B >> 26) & 0x3f);
719 	num_str_bins_ib = fft_summary_B & 0xff;
720 	base_pwr = ((fft_summary_A >> 14) & 0x1ff);
721 	total_gain_info = ((fft_summary_A >> 23) & 0x1ff);
722 
723 	fft_chn_idx = ((fft_summary_A >> 12) & 0x3);
724 	peak_inx = fft_summary_A & 0xfff;
725 
726 	if (peak_inx > 2047)
727 		peak_inx = peak_inx - 4096;
728 
729 	avgpwr_db = ((fft_summary_B >> 18) & 0xff);
730 	peak_mag = ((fft_summary_B >> 8) & 0x3ff);
731 
732 	spectral_debug("Header A = 0x%x Header B = 0x%x",
733 		       phdr->hdr_a, phdr->hdr_b);
734 	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",
735 		       base_pwr, total_gain_info, relpwr_db, num_str_bins_ib,
736 		       fft_chn_idx, peak_inx, avgpwr_db, peak_mag);
737 	if (is_160_format) {
738 		segid = fft_summary_C & 0x1;
739 		spectral_debug("Segment ID: %hhu", segid);
740 	}
741 
742 	spectral_debug("FFT bins:");
743 	for (i = 0; i < (tlvlen - 8 - segid_skiplen); i++) {
744 		fft_mag = ((uint8_t *)ptlv)[12 + segid_skiplen + i];
745 		spectral_debug("%d %d, ", i, fft_mag);
746 	}
747 
748 	spectral_debug("\n");
749 
750 	return 0;
751 }
752 
753 #ifdef SPECTRAL_DEBUG_SAMP_MSG
754 /**
755  * target_if_spectral_log_SAMP_param() - Log SAMP parameters
756  * @params: Reference to target_if_samp_msg_params
757  *
758  * API to log spectral SAMP message parameters
759  *
760  * Return: None
761  */
762 static void
763 target_if_spectral_log_SAMP_param(struct target_if_samp_msg_params *params)
764 {
765 	target_if_dbg_print_samp_param(params);
766 }
767 
768 #else
769 static void
770 target_if_spectral_log_SAMP_param(struct target_if_samp_msg_params *params)
771 {
772 }
773 #endif
774 
775 int
776 target_if_process_phyerr_gen2(struct target_if_spectral *spectral,
777 			      uint8_t *data,
778 			      uint32_t datalen,
779 			      struct target_if_spectral_rfqual_info *p_rfqual,
780 			      struct target_if_spectral_chan_info *p_chaninfo,
781 			      uint64_t tsf64,
782 			      struct target_if_spectral_acs_stats *acs_stats)
783 {
784 	/*
785 	 * XXX : The classifier do not use all the members of the SAMP
786 	 *       message data format.
787 	 *       The classifier only depends upon the following parameters
788 	 *
789 	 *          1. Frequency (freq, msg->freq)
790 	 *          2. Spectral RSSI (spectral_rssi,
791 	 *          msg->samp_data.spectral_rssi)
792 	 *          3. Bin Power Count (bin_pwr_count,
793 	 *          msg->samp_data.bin_pwr_count)
794 	 *          4. Bin Power values (bin_pwr, msg->samp_data.bin_pwr[0]
795 	 *          5. Spectral Timestamp (spectral_tstamp,
796 	 *          msg->samp_data.spectral_tstamp)
797 	 *          6. MAC Address (macaddr, msg->macaddr)
798 	 *
799 	 *       This function prepares the params structure and populates it
800 	 *       with
801 	 *       relevant values, this is in turn passed to
802 	 *       spectral_create_samp_msg()
803 	 *       to prepare fully formatted Spectral SAMP message
804 	 *
805 	 *       XXX : Need to verify
806 	 *          1. Order of FFT bin values
807 	 *
808 	 */
809 
810 	struct target_if_samp_msg_params params;
811 	struct spectral_search_fft_info_gen2 search_fft_info;
812 	struct spectral_search_fft_info_gen2 *p_sfft = &search_fft_info;
813 	struct spectral_search_fft_info_gen2 search_fft_info_sec80;
814 	struct spectral_search_fft_info_gen2 *p_sfft_sec80 =
815 		&search_fft_info_sec80;
816 	uint32_t segid_skiplen = 0;
817 
818 	int8_t rssi_up = 0;
819 	int8_t rssi_low = 0;
820 
821 	int8_t chn_idx_highest_enabled = 0;
822 	int8_t chn_idx_lowest_enabled = 0;
823 
824 	uint8_t control_rssi = 0;
825 	uint8_t extension_rssi = 0;
826 	uint8_t combined_rssi = 0;
827 
828 	uint32_t tstamp = 0;
829 
830 	struct target_if_spectral_ops *p_sops =
831 		GET_TARGET_IF_SPECTRAL_OPS(spectral);
832 
833 	struct spectral_phyerr_tlv_gen2 *ptlv =
834 		(struct spectral_phyerr_tlv_gen2 *)data;
835 	struct spectral_phyerr_tlv_gen2 *ptlv_sec80 = NULL;
836 	struct spectral_phyerr_fft_gen2 *pfft = NULL;
837 	struct spectral_phyerr_fft_gen2 *pfft_sec80 = NULL;
838 
839 	uint8_t segid = 0;
840 	uint8_t segid_sec80 = 0;
841 	enum phy_ch_width ch_width =
842 				spectral->ch_width[SPECTRAL_SCAN_MODE_NORMAL];
843 
844 	if (spectral->is_160_format)
845 		segid_skiplen = sizeof(SPECTRAL_SEGID_INFO);
846 
847 	pfft = (struct spectral_phyerr_fft_gen2 *)(
848 			data +
849 			sizeof(struct spectral_phyerr_tlv_gen2) +
850 			sizeof(struct spectral_phyerr_hdr_gen2) +
851 			segid_skiplen);
852 
853 	/*
854 	 * XXX Extend SPECTRAL_DPRINTK() to use spectral_debug_level,
855 	 * and use this facility inside spectral_dump_phyerr_data()
856 	 * and supporting functions.
857 	 */
858 	if (spectral_debug_level & DEBUG_SPECTRAL2)
859 		target_if_spectral_dump_phyerr_data_gen2(
860 					data, datalen,
861 					spectral->is_160_format);
862 
863 	if (spectral_debug_level & DEBUG_SPECTRAL4) {
864 		target_if_spectral_dump_phyerr_data_gen2(
865 					data, datalen,
866 					spectral->is_160_format);
867 		spectral_debug_level = DEBUG_SPECTRAL;
868 	}
869 
870 	if (ptlv->signature != SPECTRAL_PHYERR_SIGNATURE_GEN2) {
871 		/*
872 		 * EV# 118023: We tentatively disable the below print
873 		 * and provide stats instead.
874 		 */
875 		spectral->diag_stats.spectral_mismatch++;
876 		return -EPERM;
877 	}
878 
879 	OS_MEMZERO(&params, sizeof(params));
880 	/* Gen 2 only supports normal Spectral scan currently */
881 	params.smode = SPECTRAL_SCAN_MODE_NORMAL;
882 
883 	if (ptlv->tag == TLV_TAG_SEARCH_FFT_REPORT_GEN2) {
884 		if (spectral->is_160_format) {
885 			segid = *((SPECTRAL_SEGID_INFO *)(
886 				  (uint8_t *)ptlv +
887 				  sizeof(struct spectral_phyerr_tlv_gen2) +
888 				  sizeof(struct spectral_phyerr_hdr_gen2)));
889 
890 			if (segid != 0) {
891 				struct spectral_diag_stats *p_diag_stats =
892 					&spectral->diag_stats;
893 				p_diag_stats->spectral_vhtseg1id_mismatch++;
894 				return -EPERM;
895 			}
896 		}
897 
898 		target_if_process_sfft_report_gen2(ptlv, ptlv->length,
899 						   &search_fft_info);
900 
901 		tstamp = p_sops->get_tsf64(spectral) & SPECTRAL_TSMASK;
902 
903 		combined_rssi = p_rfqual->rssi_comb;
904 
905 		if (spectral->upper_is_control)
906 			rssi_up = control_rssi;
907 		else
908 			rssi_up = extension_rssi;
909 
910 		if (spectral->lower_is_control)
911 			rssi_low = control_rssi;
912 		else
913 			rssi_low = extension_rssi;
914 
915 		params.rssi = p_rfqual->rssi_comb;
916 		params.lower_rssi = rssi_low;
917 		params.upper_rssi = rssi_up;
918 
919 		if (spectral->sc_spectral_noise_pwr_cal) {
920 			params.chain_ctl_rssi[0] =
921 			    p_rfqual->pc_rssi_info[0].rssi_pri20;
922 			params.chain_ctl_rssi[1] =
923 			    p_rfqual->pc_rssi_info[1].rssi_pri20;
924 			params.chain_ctl_rssi[2] =
925 			    p_rfqual->pc_rssi_info[2].rssi_pri20;
926 			params.chain_ext_rssi[0] =
927 			    p_rfqual->pc_rssi_info[0].rssi_sec20;
928 			params.chain_ext_rssi[1] =
929 			    p_rfqual->pc_rssi_info[1].rssi_sec20;
930 			params.chain_ext_rssi[2] =
931 			    p_rfqual->pc_rssi_info[2].rssi_sec20;
932 		}
933 
934 		/*
935 		 * XXX : This actually depends on the programmed chain mask
936 		 *       This value decides the per-chain enable mask to select
937 		 *       the input ADC for search FTT.
938 		 *       For modes upto VHT80, if more than one chain is
939 		 *       enabled, the max valid chain
940 		 *       is used. LSB corresponds to chain zero.
941 		 *       For VHT80_80 and VHT160, the lowest enabled chain is
942 		 *       used for primary
943 		 *       detection and highest enabled chain is used for
944 		 *       secondary detection.
945 		 *
946 		 * XXX : The current algorithm do not use these control and
947 		 *       extension channel
948 		 *       Instead, it just relies on the combined RSSI values
949 		 *       only.
950 		 *       For fool-proof detection algorithm, we should take
951 		 *       these RSSI values in to account.
952 		 *       This is marked for future enhancements.
953 		 */
954 		chn_idx_highest_enabled =
955 		   ((spectral->params[params.smode].ss_chn_mask & 0x8) ? 3 :
956 		    (spectral->params[params.smode].ss_chn_mask & 0x4) ? 2 :
957 		    (spectral->params[params.smode].ss_chn_mask & 0x2) ? 1 : 0);
958 		chn_idx_lowest_enabled =
959 		   ((spectral->params[params.smode].ss_chn_mask & 0x1) ? 0 :
960 		    (spectral->params[params.smode].ss_chn_mask & 0x2) ? 1 :
961 		    (spectral->params[params.smode].ss_chn_mask & 0x4) ? 2 : 3);
962 		control_rssi = (uint8_t)
963 		    p_rfqual->pc_rssi_info[chn_idx_highest_enabled].rssi_pri20;
964 		extension_rssi = (uint8_t)
965 		    p_rfqual->pc_rssi_info[chn_idx_highest_enabled].rssi_sec20;
966 
967 		params.bwinfo = 0;
968 		params.tstamp = 0;
969 		params.max_mag = p_sfft->peak_mag;
970 
971 		params.max_index = p_sfft->peak_inx;
972 		params.max_exp = 0;
973 		params.peak = 0;
974 		params.bin_pwr_data = (uint8_t *)pfft;
975 		params.freq = p_sops->get_current_channel(spectral);
976 		params.freq_loading = 0;
977 
978 		params.interf_list.count = 0;
979 		params.max_lower_index = 0;
980 		params.max_upper_index = 0;
981 		params.nb_lower = 0;
982 		params.nb_upper = 0;
983 		/*
984 		 * For modes upto VHT80, the noise floor is populated with the
985 		 * one corresponding
986 		 * to the highest enabled antenna chain
987 		 */
988 		params.noise_floor =
989 		    p_rfqual->noise_floor[chn_idx_highest_enabled];
990 		params.datalen = ptlv->length;
991 		params.pwr_count = ptlv->length -
992 		    sizeof(struct spectral_phyerr_hdr_gen2) - segid_skiplen;
993 		params.tstamp = (tsf64 & SPECTRAL_TSMASK);
994 
995 		acs_stats->ctrl_nf = params.noise_floor;
996 		acs_stats->ext_nf = params.noise_floor;
997 		acs_stats->nfc_ctl_rssi = control_rssi;
998 		acs_stats->nfc_ext_rssi = extension_rssi;
999 
1000 		if (spectral->is_160_format &&
1001 		    is_ch_width_160_or_80p80(ch_width)) {
1002 			/*
1003 			 * We expect to see one more Search FFT report, and it
1004 			 * should be equal in size to the current one.
1005 			 */
1006 			if (datalen < (
1007 				2 * (
1008 				sizeof(struct spectral_phyerr_tlv_gen2) +
1009 				ptlv->length))) {
1010 				struct spectral_diag_stats *p_diag_stats =
1011 					&spectral->diag_stats;
1012 				p_diag_stats->spectral_sec80_sfft_insufflen++;
1013 				return -EPERM;
1014 			}
1015 
1016 			ptlv_sec80 = (struct spectral_phyerr_tlv_gen2 *)(
1017 				      data +
1018 				      sizeof(struct spectral_phyerr_tlv_gen2) +
1019 				      ptlv->length);
1020 
1021 			if (ptlv_sec80->signature !=
1022 			    SPECTRAL_PHYERR_SIGNATURE_GEN2) {
1023 				spectral->diag_stats.spectral_mismatch++;
1024 				return -EPERM;
1025 			}
1026 
1027 			if (ptlv_sec80->tag != TLV_TAG_SEARCH_FFT_REPORT_GEN2) {
1028 				spectral->diag_stats.spectral_no_sec80_sfft++;
1029 				return -EPERM;
1030 			}
1031 
1032 			segid_sec80 = *((SPECTRAL_SEGID_INFO *)(
1033 				(uint8_t *)ptlv_sec80 +
1034 				sizeof(struct spectral_phyerr_tlv_gen2) +
1035 				sizeof(struct spectral_phyerr_hdr_gen2)));
1036 
1037 			if (segid_sec80 != 1) {
1038 				struct spectral_diag_stats *p_diag_stats =
1039 					&spectral->diag_stats;
1040 				p_diag_stats->spectral_vhtseg2id_mismatch++;
1041 				return -EPERM;
1042 			}
1043 
1044 			params.vhtop_ch_freq_seg1 = p_chaninfo->center_freq1;
1045 			params.vhtop_ch_freq_seg2 = p_chaninfo->center_freq2;
1046 
1047 			target_if_process_sfft_report_gen2(
1048 				ptlv_sec80,
1049 				ptlv_sec80->length,
1050 				&search_fft_info_sec80);
1051 
1052 			pfft_sec80 = (struct spectral_phyerr_fft_gen2 *)(
1053 				((uint8_t *)ptlv_sec80) +
1054 				sizeof(struct spectral_phyerr_tlv_gen2) +
1055 				sizeof(struct spectral_phyerr_hdr_gen2) +
1056 				segid_skiplen);
1057 
1058 			/* XXX: Confirm. TBD at SoD. */
1059 			params.rssi_sec80 = p_rfqual->rssi_comb;
1060 			if (spectral->is_sec80_rssi_war_required)
1061 				params.rssi_sec80 =
1062 				    target_if_get_combrssi_sec80_seg_gen2
1063 				    (spectral, &search_fft_info_sec80);
1064 			/* XXX: Determine dynamically. TBD at SoD. */
1065 			/*
1066 			 * For VHT80_80/VHT160, the noise floor for primary
1067 			 * 80MHz segment is populated with the
1068 			 * lowest enabled antenna chain and the noise floor for
1069 			 * secondary 80MHz segment is populated
1070 			 * with the highest enabled antenna chain
1071 			 */
1072 			params.noise_floor_sec80 =
1073 			    p_rfqual->noise_floor[chn_idx_highest_enabled];
1074 			params.noise_floor =
1075 			    p_rfqual->noise_floor[chn_idx_lowest_enabled];
1076 
1077 			params.max_mag_sec80 = p_sfft_sec80->peak_mag;
1078 			params.max_index_sec80 = p_sfft_sec80->peak_inx;
1079 			/* XXX Does this definition of datalen *still hold? */
1080 			params.datalen_sec80 = ptlv_sec80->length;
1081 			params.pwr_count_sec80 =
1082 			    ptlv_sec80->length -
1083 			    sizeof(struct spectral_phyerr_hdr_gen2) -
1084 			    segid_skiplen;
1085 			params.bin_pwr_data_sec80 = (uint8_t *)pfft_sec80;
1086 		}
1087 		qdf_mem_copy(&params.classifier_params,
1088 			     &spectral->classifier_params,
1089 			     sizeof(struct spectral_classifier_params));
1090 
1091 		target_if_spectral_log_SAMP_param(&params);
1092 		target_if_spectral_create_samp_msg(spectral, &params);
1093 	}
1094 
1095 	return 0;
1096 }
1097 
1098 int
1099 target_if_spectral_dump_hdr_gen2(struct spectral_phyerr_hdr_gen2 *phdr)
1100 {
1101 	uint32_t a = 0;
1102 	uint32_t b = 0;
1103 
1104 	qdf_mem_copy(&a, (uint8_t *)phdr, sizeof(int));
1105 	qdf_mem_copy(&b,
1106 		     (uint8_t *)((uint8_t *)phdr + sizeof(int)),
1107 		     sizeof(int));
1108 
1109 	spectral_debug("SPECTRAL : HEADER A 0x%x (%d)", a, a);
1110 	spectral_debug("SPECTRAL : HEADER B 0x%x (%d)", b, b);
1111 	return 0;
1112 }
1113 
1114 int8_t
1115 target_if_get_combrssi_sec80_seg_gen2(
1116 	struct target_if_spectral *spectral,
1117 	struct spectral_search_fft_info_gen2 *p_sfft_sec80)
1118 {
1119 	uint32_t avgpwr_db = 0;
1120 	uint32_t total_gain_db = 0;
1121 	uint32_t offset = 0;
1122 	int8_t comb_rssi = 0;
1123 
1124 	/* Obtain required parameters for algorithm from search FFT report */
1125 	avgpwr_db = p_sfft_sec80->avgpwr_db;
1126 	total_gain_db = p_sfft_sec80->total_gain_info;
1127 
1128 	/* Calculate offset */
1129 	offset = target_if_get_offset_swar_sec80(
1130 			spectral->ch_width[SPECTRAL_SCAN_MODE_NORMAL]);
1131 
1132 	/* Calculate RSSI */
1133 	comb_rssi = ((avgpwr_db - total_gain_db) + offset);
1134 
1135 	return comb_rssi;
1136 }
1137 
1138 int
1139 target_if_spectral_dump_tlv_gen2(
1140 	struct spectral_phyerr_tlv_gen2 *ptlv, bool is_160_format)
1141 {
1142 	int ret = 0;
1143 
1144 	/*
1145 	 * TODO : Do not delete the following print
1146 	 *        The scripts used to validate Spectral depend on this Print
1147 	 */
1148 	spectral_debug("SPECTRAL : TLV Length is 0x%x (%d)",
1149 		       ptlv->length, ptlv->length);
1150 
1151 	switch (ptlv->tag) {
1152 	case TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN2:
1153 		ret =
1154 		    target_if_dump_summary_report_gen2(
1155 			ptlv, ptlv->length, is_160_format);
1156 		break;
1157 
1158 	case TLV_TAG_SEARCH_FFT_REPORT_GEN2:
1159 		ret =
1160 		    target_if_dump_sfft_report_gen2(ptlv, ptlv->length,
1161 						    is_160_format);
1162 		break;
1163 
1164 	case TLV_TAG_ADC_REPORT_GEN2:
1165 		ret = target_if_dump_adc_report_gen2(ptlv, ptlv->length);
1166 		break;
1167 
1168 	default:
1169 		spectral_warn("INVALID TLV");
1170 		ret = -1;
1171 		break;
1172 	}
1173 
1174 	return ret;
1175 }
1176 
1177 int
1178 target_if_spectral_dump_phyerr_data_gen2(uint8_t *data, uint32_t datalen,
1179 					 bool is_160_format)
1180 {
1181 	struct spectral_phyerr_tlv_gen2 *ptlv = NULL;
1182 	uint32_t bytes_processed = 0;
1183 	uint32_t bytes_remaining = datalen;
1184 	uint32_t curr_tlv_complete_size = 0;
1185 
1186 	if (datalen < sizeof(struct spectral_phyerr_tlv_gen2)) {
1187 		spectral_err("Total PHY error data length %u too short to contain any TLVs",
1188 			     datalen);
1189 		return -EPERM;
1190 	}
1191 
1192 	while (bytes_processed < datalen) {
1193 		if (bytes_remaining < sizeof(struct spectral_phyerr_tlv_gen2)) {
1194 			spectral_err("Remaining PHY error data length %u too short to contain a TLV",
1195 				     bytes_remaining);
1196 			return -EPERM;
1197 		}
1198 
1199 		ptlv = (struct spectral_phyerr_tlv_gen2 *)(data +
1200 							   bytes_processed);
1201 
1202 		if (ptlv->signature != SPECTRAL_PHYERR_SIGNATURE_GEN2) {
1203 			spectral_err("Invalid signature 0x%x!",
1204 				     ptlv->signature);
1205 			return -EPERM;
1206 		}
1207 
1208 		curr_tlv_complete_size =
1209 			sizeof(struct spectral_phyerr_tlv_gen2) +
1210 			ptlv->length;
1211 
1212 		if (curr_tlv_complete_size > bytes_remaining) {
1213 			spectral_err("TLV size %d greater than number of bytes remaining %d",
1214 				     curr_tlv_complete_size, bytes_remaining);
1215 			return -EPERM;
1216 		}
1217 
1218 		if (target_if_spectral_dump_tlv_gen2(ptlv, is_160_format) == -1)
1219 			return -EPERM;
1220 
1221 		bytes_processed += curr_tlv_complete_size;
1222 		bytes_remaining = datalen - bytes_processed;
1223 	}
1224 
1225 	return 0;
1226 }
1227 
1228 #ifdef DIRECT_BUF_RX_ENABLE
1229 /**
1230  * target_if_get_spectral_mode() - Get Spectral scan mode corresponding to a
1231  * detector id
1232  * @detector_id: detector id in the Spectral report
1233  * @rparams: pointer to report params object
1234  *
1235  * Helper API to get Spectral scan mode from the detector ID. This mapping is
1236  * target specific.
1237  *
1238  * Return: Spectral scan mode
1239  */
1240 static enum spectral_scan_mode
1241 target_if_get_spectral_mode(enum spectral_detector_id detector_id,
1242 			    struct spectral_report_params *rparams)
1243 {
1244 	if (detector_id >= SPECTRAL_DETECTOR_ID_MAX) {
1245 		spectral_err_rl("Invalid detector id %d", detector_id);
1246 		return SPECTRAL_SCAN_MODE_INVALID;
1247 	}
1248 
1249 	return rparams->detid_mode_table[detector_id];
1250 }
1251 
1252 /**
1253  * target_if_spectral_get_bin_count_after_len_adj() - Get number of FFT bins in
1254  * Spectral FFT report
1255  * @fft_bin_len: FFT bin length reported by target
1256  * @rpt_mode: Spectral report mode
1257  * @swar: Spectral FFT bin length adjustments SWAR parameters
1258  * @fft_bin_size: Size of one FFT bin in bytes
1259  *
1260  * Get actual number of FFT bins in the FFT report after adjusting the length
1261  * by applying the SWARs for getting correct length.
1262  *
1263  * Return: FFT bin count
1264  */
1265 static size_t
1266 target_if_spectral_get_bin_count_after_len_adj(
1267 				size_t fft_bin_len, uint8_t rpt_mode,
1268 				struct spectral_fft_bin_len_adj_swar *swar,
1269 				size_t *fft_bin_size)
1270 {
1271 	size_t fft_bin_count = fft_bin_len;
1272 
1273 	if (rpt_mode == 1 && swar->null_fftbin_adj) {
1274 		/*
1275 		 * No FFT bins are expected. Explicitly set FFT bin
1276 		 * count to 0.
1277 		 */
1278 		fft_bin_count = 0;
1279 		*fft_bin_size = 0;
1280 	} else {
1281 		/*
1282 		 * Divide fft bin length by appropriate factor depending
1283 		 * on the value of fftbin_size_war.
1284 		 */
1285 		switch (swar->fftbin_size_war) {
1286 		case SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE:
1287 			fft_bin_count >>= 2;
1288 			*fft_bin_size = 4;
1289 			break;
1290 		case SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE:
1291 			fft_bin_count >>= 1;
1292 			*fft_bin_size = 2;
1293 			/* Ideally we should be dividing fft bin length
1294 			 * by 2. Due to a HW bug, actual length is two
1295 			 * times the expected length.
1296 			 */
1297 			if (swar->packmode_fftbin_size_adj)
1298 				fft_bin_count >>= 1;
1299 			break;
1300 		case SPECTRAL_FFTBIN_SIZE_NO_WAR:
1301 			*fft_bin_size = 1;
1302 			/* No length adjustment */
1303 			break;
1304 		default:
1305 			qdf_assert_always(0);
1306 		}
1307 
1308 		if (rpt_mode == 2 && swar->inband_fftbin_size_adj)
1309 			fft_bin_count >>= 1;
1310 	}
1311 
1312 	return fft_bin_count;
1313 }
1314 
1315 /**
1316  * target_if_process_sfft_report_gen3() - Process Search FFT Report for gen3
1317  * @p_fft_report: Pointer to fft report
1318  * @p_sfft: Pointer to search fft report
1319  *
1320  * Process Search FFT Report for gen3
1321  *
1322  * Return: Success/Failure
1323  */
1324 static int
1325 target_if_process_sfft_report_gen3(
1326 	struct spectral_phyerr_fft_report_gen3 *p_fft_report,
1327 	struct spectral_search_fft_info_gen3 *p_sfft)
1328 {
1329 	/*
1330 	 * For simplicity, everything is defined as uint32_t (except one).
1331 	 * Proper code will later use the right sizes.
1332 	 */
1333 	/*
1334 	 * For easy comparision between MDK team and OS team, the MDK script
1335 	 * variable names have been used
1336 	 */
1337 	int32_t peak_sidx;
1338 	int32_t peak_mag;
1339 
1340 	/* Populate the Search FFT Info */
1341 	if (p_sfft) {
1342 		p_sfft->timestamp = p_fft_report->fft_timestamp;
1343 
1344 		p_sfft->fft_detector_id = get_bitfield(p_fft_report->hdr_a,
1345 						       2, 0);
1346 		p_sfft->fft_num = get_bitfield(p_fft_report->hdr_a, 3, 2);
1347 		p_sfft->fft_radar_check = get_bitfield(p_fft_report->hdr_a,
1348 						       12, 5);
1349 
1350 		peak_sidx = get_bitfield(p_fft_report->hdr_a, 11, 17);
1351 		p_sfft->fft_peak_sidx = unsigned_to_signed(peak_sidx, 11);
1352 		p_sfft->fft_chn_idx = get_bitfield(p_fft_report->hdr_a, 3, 28);
1353 
1354 		p_sfft->fft_base_pwr_db = get_bitfield(p_fft_report->hdr_b,
1355 						       9, 0);
1356 		p_sfft->fft_total_gain_db = get_bitfield(p_fft_report->hdr_b,
1357 							 8, 9);
1358 
1359 		p_sfft->fft_num_str_bins_ib = get_bitfield(p_fft_report->hdr_c,
1360 							   8, 0);
1361 		peak_mag = get_bitfield(p_fft_report->hdr_c, 10, 8);
1362 		p_sfft->fft_peak_mag = unsigned_to_signed(peak_mag, 10);
1363 		p_sfft->fft_avgpwr_db = get_bitfield(p_fft_report->hdr_c,
1364 						     7, 18);
1365 		p_sfft->fft_relpwr_db = get_bitfield(p_fft_report->hdr_c,
1366 						     7, 25);
1367 	}
1368 
1369 	return 0;
1370 }
1371 
1372 /**
1373  * target_if_dump_fft_report_gen3() - Dump FFT Report for gen3
1374  * @spectral: Pointer to Spectral object
1375  * @smode: Spectral scan mode
1376  * @p_fft_report: Pointer to fft report
1377  * @p_sfft: Pointer to search fft report
1378  *
1379  * Dump FFT Report for gen3
1380  *
1381  * Return: void
1382  */
1383 static void
1384 target_if_dump_fft_report_gen3(struct target_if_spectral *spectral,
1385 			enum spectral_scan_mode smode,
1386 			struct spectral_phyerr_fft_report_gen3 *p_fft_report,
1387 			struct spectral_search_fft_info_gen3 *p_sfft)
1388 {
1389 	size_t fft_hdr_length = (p_fft_report->fft_hdr_length * 4);
1390 	size_t report_len = (fft_hdr_length + 8);
1391 	size_t fft_bin_len;
1392 	size_t fft_bin_count;
1393 	size_t fft_bin_size;
1394 	size_t fft_bin_len_inband_tfer = 0;
1395 	uint8_t *fft_bin_buf = NULL;
1396 
1397 	fft_bin_len = fft_hdr_length - spectral->rparams.fft_report_hdr_len;
1398 	fft_bin_count = target_if_spectral_get_bin_count_after_len_adj(
1399 			fft_bin_len,
1400 			spectral->params[smode].ss_rpt_mode,
1401 			&spectral->len_adj_swar, &fft_bin_size);
1402 
1403 	if ((spectral->params[smode].ss_rpt_mode == 2) &&
1404 	    spectral->len_adj_swar.inband_fftbin_size_adj)
1405 		fft_bin_len_inband_tfer = fft_bin_len >> 1;
1406 
1407 	spectral_debug("Spectral FFT Report");
1408 	spectral_debug("fft_timestamp = 0x%x", p_fft_report->fft_timestamp);
1409 	spectral_debug("fft_hdr_length = %u(32 bit words)",
1410 		       p_fft_report->fft_hdr_length);
1411 	spectral_debug("fft_hdr_tag = 0x%x", p_fft_report->fft_hdr_tag);
1412 	spectral_debug("fft_hdr_sig = 0x%x", p_fft_report->fft_hdr_sig);
1413 
1414 	spectral_debug("Length field in search fft report is %zu(0x%zx) bytes",
1415 		       fft_hdr_length, fft_hdr_length);
1416 	spectral_debug("Total length of search fft report is %zu(0x%zx) bytes",
1417 		       report_len, report_len);
1418 	spectral_debug("Target reported fftbins in report is %zu(0x%zx)",
1419 		       fft_bin_len, fft_bin_len);
1420 
1421 	if ((spectral->params[smode].ss_rpt_mode == 1) &&
1422 	    spectral->len_adj_swar.null_fftbin_adj)
1423 		spectral_debug("WAR: Considering number of FFT bins as 0");
1424 	else if ((spectral->params[smode].ss_rpt_mode == 2) &&
1425 		 spectral->len_adj_swar.inband_fftbin_size_adj) {
1426 		spectral_debug("FW fftbins actually transferred (in-band report mode) %zu(0x%zx)",
1427 			       fft_bin_len_inband_tfer,
1428 			       fft_bin_len_inband_tfer);
1429 	}
1430 
1431 	spectral_debug("Actual number of fftbins in report is %zu(0x%zx)",
1432 		       fft_bin_count, fft_bin_count);
1433 
1434 	spectral_debug("fft_detector_id = %u", p_sfft->fft_detector_id);
1435 	spectral_debug("fft_num = %u", p_sfft->fft_num);
1436 	spectral_debug("fft_radar_check = %u", p_sfft->fft_radar_check);
1437 	spectral_debug("fft_peak_sidx = %d",  p_sfft->fft_peak_sidx);
1438 	spectral_debug("fft_chn_idx = %u", p_sfft->fft_chn_idx);
1439 	spectral_debug("fft_base_pwr_db = %u", p_sfft->fft_base_pwr_db);
1440 	spectral_debug("fft_total_gain_db = %u", p_sfft->fft_total_gain_db);
1441 	spectral_debug("fft_num_str_bins_ib = %u", p_sfft->fft_num_str_bins_ib);
1442 	spectral_debug("fft_peak_mag = %d", p_sfft->fft_peak_mag);
1443 	spectral_debug("fft_avgpwr_db = %u", p_sfft->fft_avgpwr_db);
1444 	spectral_debug("fft_relpwr_db = %u", p_sfft->fft_relpwr_db);
1445 
1446 	if (fft_bin_count > 0) {
1447 		int idx;
1448 
1449 		spectral_debug("FFT bins:");
1450 		if (spectral->len_adj_swar.fftbin_size_war ==
1451 				SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE) {
1452 			uint32_t *binptr_32 = (uint32_t *)&p_fft_report->buf;
1453 
1454 			fft_bin_buf = (uint8_t *)qdf_mem_malloc(MAX_NUM_BINS);
1455 			if (!fft_bin_buf) {
1456 				spectral_err("Failed to allocate memory");
1457 				return;
1458 			}
1459 			for (idx = 0; idx < fft_bin_count; idx++)
1460 				fft_bin_buf[idx] = *(binptr_32++);
1461 		} else if (spectral->len_adj_swar.fftbin_size_war ==
1462 				SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE) {
1463 			uint16_t *binptr_16 = (uint16_t *)&p_fft_report->buf;
1464 
1465 			fft_bin_buf = (uint8_t *)qdf_mem_malloc(MAX_NUM_BINS);
1466 			if (!fft_bin_buf) {
1467 				spectral_err("Failed to allocate memory");
1468 				return;
1469 			}
1470 			for (idx = 0; idx < fft_bin_count; idx++)
1471 				fft_bin_buf[idx] = *(binptr_16++);
1472 		} else {
1473 			fft_bin_buf = (uint8_t *)&p_fft_report->buf;
1474 		}
1475 		target_if_spectral_hexdump(fft_bin_buf, fft_bin_count);
1476 		if ((spectral->len_adj_swar.fftbin_size_war !=
1477 				SPECTRAL_FFTBIN_SIZE_NO_WAR) && fft_bin_buf)
1478 			qdf_mem_free(fft_bin_buf);
1479 	}
1480 }
1481 #endif
1482 
1483 QDF_STATUS
1484 target_if_160mhz_delivery_state_change(struct target_if_spectral *spectral,
1485 				       enum spectral_scan_mode smode,
1486 				       uint8_t detector_id) {
1487 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1488 
1489 	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
1490 		spectral_err_rl("Invalid Spectral mode %d", smode);
1491 		return QDF_STATUS_E_INVAL;
1492 	}
1493 
1494 	if (!is_ch_width_160_or_80p80(spectral->ch_width[smode])) {
1495 		spectral_err_rl("Scan BW %d is not 160/80p80 for mode %d",
1496 				spectral->ch_width[smode], smode);
1497 		return QDF_STATUS_E_FAILURE;
1498 	}
1499 
1500 	switch (spectral->state_160mhz_delivery[smode]) {
1501 	case SPECTRAL_REPORT_WAIT_PRIMARY80:
1502 		if (detector_id == SPECTRAL_DETECTOR_ID_0)
1503 			spectral->state_160mhz_delivery[smode] =
1504 				SPECTRAL_REPORT_RX_PRIMARY80;
1505 		else {
1506 			status = QDF_STATUS_E_FAILURE;
1507 			spectral->diag_stats.spectral_vhtseg1id_mismatch++;
1508 		}
1509 		break;
1510 
1511 	case SPECTRAL_REPORT_WAIT_SECONDARY80:
1512 		if (detector_id == SPECTRAL_DETECTOR_ID_1)
1513 			spectral->state_160mhz_delivery[smode] =
1514 				SPECTRAL_REPORT_RX_SECONDARY80;
1515 		else {
1516 			spectral->state_160mhz_delivery[smode] =
1517 				SPECTRAL_REPORT_WAIT_PRIMARY80;
1518 			status = QDF_STATUS_E_FAILURE;
1519 			spectral->diag_stats.spectral_vhtseg2id_mismatch++;
1520 		}
1521 		break;
1522 
1523 	case SPECTRAL_REPORT_RX_SECONDARY80:
1524 		/* We don't care about detector id in this state. */
1525 		reset_160mhz_delivery_state_machine(spectral, smode);
1526 		break;
1527 
1528 	case SPECTRAL_REPORT_RX_PRIMARY80:
1529 		/* We don't care about detector id in this state */
1530 		spectral->state_160mhz_delivery[smode] =
1531 				SPECTRAL_REPORT_WAIT_SECONDARY80;
1532 		break;
1533 
1534 	default:
1535 		break;
1536 	}
1537 
1538 	return status;
1539 }
1540 
1541 #ifdef DIRECT_BUF_RX_ENABLE
1542 /**
1543  * target_if_get_detector_id_sscan_summary_report_gen3() - Get Spectral detector
1544  * ID from Spectral summary report
1545  * @data: Pointer to Spectral summary report
1546  *
1547  * Return: Detector ID
1548  */
1549 static uint8_t
1550 target_if_get_detector_id_sscan_summary_report_gen3(uint8_t *data) {
1551 	struct spectral_sscan_summary_report_gen3 *psscan_summary_report;
1552 	uint8_t detector_id;
1553 
1554 	qdf_assert_always(data);
1555 
1556 	psscan_summary_report =
1557 		(struct spectral_sscan_summary_report_gen3 *)data;
1558 
1559 	detector_id = get_bitfield(
1560 			psscan_summary_report->hdr_a,
1561 			SSCAN_SUMMARY_REPORT_HDR_A_DETECTOR_ID_SIZE_GEN3,
1562 			SSCAN_SUMMARY_REPORT_HDR_A_DETECTOR_ID_POS_GEN3);
1563 
1564 	return detector_id;
1565 }
1566 
1567 /**
1568  * target_if_consume_sscan_summary_report_gen3() - Consume Spectral summary
1569  * report
1570  * @data: Pointer to Spectral summary report
1571  * @fields: Pointer to structure to be populated with extracted fields
1572  * @rparams: Pointer to structure with Spectral report params
1573  *
1574  * Consume Spectral summary report for gen3
1575  *
1576  * Return: void
1577  */
1578 static void
1579 target_if_consume_sscan_summary_report_gen3(
1580 				uint8_t *data,
1581 				struct sscan_report_fields_gen3 *fields,
1582 				struct spectral_report_params *rparams) {
1583 	struct spectral_sscan_summary_report_gen3 *psscan_summary_report;
1584 
1585 	qdf_assert_always(data);
1586 	qdf_assert_always(fields);
1587 	qdf_assert_always(rparams);
1588 
1589 	psscan_summary_report =
1590 		(struct spectral_sscan_summary_report_gen3 *)data;
1591 
1592 	fields->sscan_agc_total_gain = get_bitfield(
1593 			psscan_summary_report->hdr_a,
1594 			SSCAN_SUMMARY_REPORT_HDR_A_AGC_TOTAL_GAIN_SIZE_GEN3,
1595 			SSCAN_SUMMARY_REPORT_HDR_A_AGC_TOTAL_GAIN_POS_GEN3);
1596 	fields->inband_pwr_db = get_bitfield(
1597 			psscan_summary_report->hdr_a,
1598 			SSCAN_SUMMARY_REPORT_HDR_A_INBAND_PWR_DB_SIZE_GEN3,
1599 			SSCAN_SUMMARY_REPORT_HDR_A_INBAND_PWR_DB_POS_GEN3);
1600 	fields->sscan_pri80 = get_bitfield(
1601 			psscan_summary_report->hdr_a,
1602 			SSCAN_SUMMARY_REPORT_HDR_A_PRI80_SIZE_GEN3,
1603 			SSCAN_SUMMARY_REPORT_HDR_A_PRI80_POS_GEN3);
1604 
1605 	switch (rparams->version) {
1606 	case SPECTRAL_REPORT_FORMAT_VERSION_1:
1607 		fields->sscan_gainchange = get_bitfield(
1608 			psscan_summary_report->hdr_b,
1609 			SSCAN_SUMMARY_REPORT_HDR_B_GAINCHANGE_SIZE_GEN3_V1,
1610 			SSCAN_SUMMARY_REPORT_HDR_B_GAINCHANGE_POS_GEN3_V1);
1611 		break;
1612 	case SPECTRAL_REPORT_FORMAT_VERSION_2:
1613 		fields->sscan_gainchange = get_bitfield(
1614 			psscan_summary_report->hdr_c,
1615 			SSCAN_SUMMARY_REPORT_HDR_C_GAINCHANGE_SIZE_GEN3_V2,
1616 			SSCAN_SUMMARY_REPORT_HDR_C_GAINCHANGE_POS_GEN3_V2);
1617 		break;
1618 	default:
1619 		qdf_assert_always(0);
1620 	}
1621 }
1622 
1623 /**
1624  * target_if_verify_sig_and_tag_gen3() - Verify tag and signature
1625  *                                       of spectral report
1626  * @spectral: Pointer to spectral object
1627  * @data: Pointer to spectral summary report
1628  * @exp_tag: iexpected tag value
1629  *
1630  * Process fft report for gen3
1631  *
1632  * Return: SUCCESS/FAILURE
1633  */
1634 static int
1635 target_if_verify_sig_and_tag_gen3(struct target_if_spectral *spectral,
1636 				  uint8_t *data, uint8_t exp_tag)
1637 {
1638 	uint8_t tag = 0;
1639 	uint8_t signature = 0;
1640 
1641 	/* Peek into the data to figure out whether
1642 	 *      1) Signature matches the expected value
1643 	 *      2) What is inside the package (TAG ID is used for finding this)
1644 	 */
1645 	tag = *(data + PHYERR_HDR_TAG_POS);
1646 	signature = *(data + PHYERR_HDR_SIG_POS);
1647 
1648 	if (signature != SPECTRAL_PHYERR_SIGNATURE_GEN3) {
1649 		spectral->diag_stats.spectral_mismatch++;
1650 		return -EINVAL;
1651 	}
1652 
1653 	if (tag != exp_tag) {
1654 		spectral->diag_stats.spectral_mismatch++;
1655 		return -EINVAL;
1656 	}
1657 
1658 	return 0;
1659 }
1660 
1661 static uint8_t
1662 target_if_spectral_get_lowest_chn_idx(uint8_t chainmask)
1663 {
1664 	uint8_t idx;
1665 
1666 	for (idx = 0; idx < DBR_MAX_CHAINS; idx++) {
1667 		if (chainmask & 0x1)
1668 			break;
1669 		chainmask >>= 1;
1670 	}
1671 	return idx;
1672 }
1673 
1674 #ifdef DIRECT_BUF_RX_DEBUG
1675 static void target_if_spectral_check_buffer_poisoning(
1676 	struct target_if_spectral *spectral,
1677 	struct spectral_report *report,
1678 	int num_fft_bins, enum spectral_scan_mode smode)
1679 {
1680 	uint32_t *data;
1681 	size_t len;
1682 	size_t words_to_check =
1683 		sizeof(struct spectral_sscan_summary_report_gen3) >> 2;
1684 	bool poisoned_words_found = false;
1685 
1686 	if (!spectral) {
1687 		spectral_err_rl("Spectral LMAC object is null");
1688 		return;
1689 	}
1690 
1691 	if (!spectral->dbr_buff_debug)
1692 		return;
1693 
1694 	if (!report) {
1695 		spectral_err_rl("Spectral report is null");
1696 		return;
1697 	}
1698 
1699 	/* Add search FFT report */
1700 	if (spectral->params[smode].ss_rpt_mode > 0)
1701 		words_to_check +=
1702 			sizeof(struct spectral_phyerr_fft_report_gen3) >> 2;
1703 
1704 	/* Now add the number of FFT bins */
1705 	if (spectral->params[smode].ss_rpt_mode > 1) {
1706 		/* Caller should take care to pass correct number of FFT bins */
1707 		if (spectral->len_adj_swar.fftbin_size_war ==
1708 				SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE)
1709 			words_to_check += num_fft_bins;
1710 		else if (spectral->len_adj_swar.fftbin_size_war ==
1711 				SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE)
1712 			words_to_check += (num_fft_bins >> 1);
1713 	}
1714 
1715 	data = (uint32_t *)report->data;
1716 	for (len = 0; len < words_to_check; ++len) {
1717 		if (*data == MEM_POISON_SIGNATURE) {
1718 			spectral_err("Pattern(%x) found in Spectral search FFT report at position %zu in the buffer %pK",
1719 				     MEM_POISON_SIGNATURE,
1720 				     (len << 2), report->data);
1721 			poisoned_words_found = true;
1722 			break;
1723 		}
1724 		++data;
1725 	}
1726 
1727 	/* Crash the FW even if one word is poisoned */
1728 	if (poisoned_words_found) {
1729 		spectral_err("Pattern(%x) found in Spectral report, Hex dump of the sfft follows",
1730 			     MEM_POISON_SIGNATURE);
1731 		target_if_spectral_hexdump((unsigned char *)report->data,
1732 					   words_to_check << 2);
1733 		spectral_err("Asserting the FW");
1734 		target_if_spectral_fw_hang(spectral);
1735 	}
1736 }
1737 
1738 static void target_if_spectral_verify_ts(struct target_if_spectral *spectral,
1739 					 uint8_t *buf, uint32_t current_ts)
1740 {
1741 	if (!spectral) {
1742 		spectral_err_rl("Spectral LMAC object is null");
1743 		return;
1744 	}
1745 
1746 	if (!spectral->dbr_buff_debug)
1747 		return;
1748 
1749 	if (spectral->prev_tstamp) {
1750 		if (current_ts == spectral->prev_tstamp) {
1751 			spectral_err("Spectral timestamp(%u) in the current buffer(%pK) is equal to the previous timestamp, same report DMAed twice? Asserting the FW",
1752 				     current_ts, buf);
1753 			target_if_spectral_fw_hang(spectral);
1754 		}
1755 	}
1756 	spectral->prev_tstamp = current_ts;
1757 }
1758 #else
1759 static void target_if_spectral_check_buffer_poisoning(
1760 	struct target_if_spectral *spectral,
1761 	struct spectral_report *report,
1762 	int num_fft_bins, enum spectral_scan_mode smode)
1763 {
1764 }
1765 
1766 static void target_if_spectral_verify_ts(struct target_if_spectral *spectral,
1767 					 uint8_t *buf, uint32_t current_ts)
1768 {
1769 }
1770 #endif
1771 
1772 /**
1773  * target_if_spectral_get_adjusted_timestamp() - Adjust Spectral time
1774  * stamp to account for reset in time stamp due to target reset
1775  * @twar: Spectral time stamp WAR related information
1776  * @raw_timestamp: Spectral time stamp reported by target
1777  * @reset_delay: Reset delay at target
1778  * @smode: Spectral scan mode
1779  *
1780  * Correct time stamp to account for reset in time stamp due to target reset
1781  *
1782  * Return: Adjusted time stamp
1783  */
1784 static uint32_t
1785 target_if_spectral_get_adjusted_timestamp(struct spectral_timestamp_war *twar,
1786 					  uint32_t raw_timestamp,
1787 					  uint32_t reset_delay,
1788 					  enum spectral_scan_mode smode) {
1789 	qdf_assert_always(smode < SPECTRAL_SCAN_MODE_MAX);
1790 
1791 	if (reset_delay) {
1792 		enum spectral_scan_mode m =
1793 					SPECTRAL_SCAN_MODE_NORMAL;
1794 
1795 		/* Adjust the offset for all the Spectral modes.
1796 		 * Target will be sending the non zero reset delay for
1797 		 * the first Spectral report after reset. This delay is
1798 		 * common for all the Spectral modes.
1799 		 */
1800 		for (; m < SPECTRAL_SCAN_MODE_MAX; m++)
1801 			twar->timestamp_war_offset[m] += (reset_delay +
1802 					twar->last_fft_timestamp[m]);
1803 		twar->target_reset_count++;
1804 	}
1805 	twar->last_fft_timestamp[smode] = raw_timestamp;
1806 
1807 	return raw_timestamp + twar->timestamp_war_offset[smode];
1808 }
1809 
1810 int
1811 target_if_consume_spectral_report_gen3(
1812 	 struct target_if_spectral *spectral,
1813 	 struct spectral_report *report)
1814 {
1815 	/*
1816 	 * XXX : The classifier do not use all the members of the SAMP
1817 	 *       message data format.
1818 	 *       The classifier only depends upon the following parameters
1819 	 *
1820 	 *          1. Frequency (freq, msg->freq)
1821 	 *          2. Spectral RSSI (spectral_rssi,
1822 	 *          msg->samp_data.spectral_rssi)
1823 	 *          3. Bin Power Count (bin_pwr_count,
1824 	 *          msg->samp_data.bin_pwr_count)
1825 	 *          4. Bin Power values (bin_pwr, msg->samp_data.bin_pwr[0]
1826 	 *          5. Spectral Timestamp (spectral_tstamp,
1827 	 *          msg->samp_data.spectral_tstamp)
1828 	 *          6. MAC Address (macaddr, msg->macaddr)
1829 	 *
1830 	 *       This function prepares the params structure and populates it
1831 	 *       with
1832 	 *       relevant values, this is in turn passed to
1833 	 *       spectral_create_samp_msg()
1834 	 *       to prepare fully formatted Spectral SAMP message
1835 	 *
1836 	 *       XXX : Need to verify
1837 	 *          1. Order of FFT bin values
1838 	 *
1839 	 */
1840 	struct target_if_samp_msg_params params = {0};
1841 	struct spectral_search_fft_info_gen3 search_fft_info;
1842 	struct spectral_search_fft_info_gen3 *p_sfft = &search_fft_info;
1843 	int8_t chn_idx_lowest_enabled  = 0;
1844 	int fft_hdr_length = 0;
1845 	int report_len = 0;
1846 	size_t fft_bin_count;
1847 	size_t fft_bin_size;
1848 	struct target_if_spectral_ops *p_sops =
1849 		GET_TARGET_IF_SPECTRAL_OPS(spectral);
1850 	struct spectral_phyerr_fft_report_gen3 *p_fft_report;
1851 	int8_t rssi;
1852 	uint8_t *data = report->data;
1853 	struct wlan_objmgr_vdev *vdev;
1854 	uint8_t vdev_rxchainmask;
1855 	struct sscan_report_fields_gen3 sscan_report_fields = {0};
1856 	enum spectral_detector_id detector_id;
1857 	QDF_STATUS ret;
1858 	enum spectral_scan_mode spectral_mode = SPECTRAL_SCAN_MODE_INVALID;
1859 	uint8_t *temp;
1860 
1861 	/* Process Spectral scan summary report */
1862 	if (target_if_verify_sig_and_tag_gen3(
1863 			spectral, data,
1864 			TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN3) != 0) {
1865 		spectral_err_rl("Wrong tag/sig in sscan summary");
1866 		goto fail;
1867 	}
1868 
1869 	detector_id = target_if_get_detector_id_sscan_summary_report_gen3(data);
1870 	if (detector_id >= spectral->rparams.num_spectral_detectors) {
1871 		spectral->diag_stats.spectral_invalid_detector_id++;
1872 		spectral_err("Invalid detector id %u, expected is 0/1/2",
1873 			     detector_id);
1874 		goto fail;
1875 	}
1876 
1877 	spectral_mode = target_if_get_spectral_mode(detector_id,
1878 						    &spectral->rparams);
1879 	if (spectral_mode == SPECTRAL_SCAN_MODE_INVALID) {
1880 		spectral_err_rl("No valid Spectral mode for detector id %u",
1881 				detector_id);
1882 		goto fail;
1883 	}
1884 
1885 	target_if_consume_sscan_summary_report_gen3(data, &sscan_report_fields,
1886 						    &spectral->rparams);
1887 	/* Advance buf pointer to the search fft report */
1888 	data += sizeof(struct spectral_sscan_summary_report_gen3);
1889 	data += spectral->rparams.ssumaary_padding_bytes;
1890 	params.vhtop_ch_freq_seg1 = report->cfreq1;
1891 	params.vhtop_ch_freq_seg2 = report->cfreq2;
1892 
1893 	if (is_primaryseg_expected(spectral, spectral_mode)) {
1894 		/* RSSI is in 1/2 dBm steps, Covert it to dBm scale */
1895 		rssi = (sscan_report_fields.inband_pwr_db) >> 1;
1896 		params.agc_total_gain =
1897 			sscan_report_fields.sscan_agc_total_gain;
1898 		params.gainchange = sscan_report_fields.sscan_gainchange;
1899 		params.pri80ind = sscan_report_fields.sscan_pri80;
1900 
1901 		/* Process Spectral search FFT report */
1902 		if (target_if_verify_sig_and_tag_gen3(
1903 				spectral, data,
1904 				TLV_TAG_SEARCH_FFT_REPORT_GEN3) != 0) {
1905 			spectral_err_rl("Unexpected tag/sig in sfft, detid= %u",
1906 					detector_id);
1907 			goto fail;
1908 		}
1909 		p_fft_report = (struct spectral_phyerr_fft_report_gen3 *)data;
1910 		fft_hdr_length = p_fft_report->fft_hdr_length * 4;
1911 		if (fft_hdr_length < 16) {
1912 			spectral_err("Wrong TLV length %u, detector id = %d",
1913 				     fft_hdr_length, detector_id);
1914 			goto fail;
1915 		}
1916 
1917 		report_len = (fft_hdr_length + 8);
1918 
1919 		target_if_process_sfft_report_gen3(p_fft_report, p_sfft);
1920 		/* It is expected to have same detector id for
1921 		 * summary and fft report
1922 		 */
1923 		if (detector_id != p_sfft->fft_detector_id) {
1924 			spectral_err_rl
1925 				("Different detid in ssummary(%u) and sfft(%u)",
1926 				 detector_id, p_sfft->fft_detector_id);
1927 			goto fail;
1928 		}
1929 
1930 		if (detector_id > spectral->rparams.num_spectral_detectors) {
1931 			spectral->diag_stats.spectral_invalid_detector_id++;
1932 			spectral_err("Invalid detector id %u, expected is 0/2",
1933 				     detector_id);
1934 			goto fail;
1935 		}
1936 		params.smode = spectral_mode;
1937 
1938 		fft_bin_count = target_if_spectral_get_bin_count_after_len_adj(
1939 			fft_hdr_length - spectral->rparams.fft_report_hdr_len,
1940 			spectral->params[spectral_mode].ss_rpt_mode,
1941 			&spectral->len_adj_swar, &fft_bin_size);
1942 
1943 		params.last_raw_timestamp = spectral->timestamp_war.
1944 				last_fft_timestamp[spectral_mode];
1945 		params.reset_delay = report->reset_delay;
1946 		params.raw_timestamp = p_sfft->timestamp;
1947 		params.tstamp = target_if_spectral_get_adjusted_timestamp(
1948 					&spectral->timestamp_war,
1949 					p_sfft->timestamp, report->reset_delay,
1950 					spectral_mode);
1951 		params.timestamp_war_offset = spectral->timestamp_war.
1952 				timestamp_war_offset[spectral_mode];
1953 		params.target_reset_count = spectral->timestamp_war.
1954 				target_reset_count;
1955 
1956 		/* Take care of state transitions for 160 MHz and 80p80 */
1957 		if (is_ch_width_160_or_80p80(spectral->ch_width
1958 		    [spectral_mode]) && spectral->rparams.
1959 		    fragmentation_160[spectral_mode]) {
1960 			ret = target_if_160mhz_delivery_state_change(
1961 					spectral, spectral_mode,
1962 					detector_id);
1963 			if (ret != QDF_STATUS_SUCCESS)
1964 				goto fail;
1965 		}
1966 
1967 		if (spectral_debug_level & (DEBUG_SPECTRAL2 | DEBUG_SPECTRAL4))
1968 			target_if_dump_fft_report_gen3(spectral, spectral_mode,
1969 						       p_fft_report, p_sfft);
1970 
1971 		params.rssi         = rssi;
1972 
1973 		vdev = target_if_spectral_get_vdev(spectral);
1974 		if (!vdev) {
1975 			spectral_info("First vdev is NULL");
1976 			reset_160mhz_delivery_state_machine(
1977 						spectral, spectral_mode);
1978 			return -EPERM;
1979 		}
1980 		vdev_rxchainmask = wlan_vdev_mlme_get_rxchainmask(vdev);
1981 		QDF_ASSERT(vdev_rxchainmask != 0);
1982 		wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
1983 
1984 		chn_idx_lowest_enabled =
1985 		target_if_spectral_get_lowest_chn_idx(vdev_rxchainmask);
1986 		if (chn_idx_lowest_enabled >= DBR_MAX_CHAINS) {
1987 			spectral_err("Invalid chain index, detector id = %u",
1988 				     detector_id);
1989 			goto fail;
1990 		}
1991 
1992 		params.max_mag  = p_sfft->fft_peak_mag;
1993 
1994 		params.freq = p_sops->get_current_channel(spectral);
1995 		params.agile_freq1 = spectral->params[SPECTRAL_SCAN_MODE_AGILE].
1996 				     ss_frequency.cfreq1;
1997 		params.agile_freq2 = spectral->params[SPECTRAL_SCAN_MODE_AGILE].
1998 				     ss_frequency.cfreq2;
1999 		params.noise_floor =
2000 			report->noisefloor[chn_idx_lowest_enabled];
2001 		temp = (uint8_t *)p_fft_report + SPECTRAL_FFT_BINS_POS;
2002 		if (is_ch_width_160_or_80p80(spectral->ch_width
2003 		    [spectral_mode]) && !spectral->rparams.
2004 		    fragmentation_160[spectral_mode]) {
2005 			struct wlan_objmgr_psoc *psoc;
2006 			struct spectral_fft_bin_markers_160_165mhz *marker;
2007 
2008 			qdf_assert_always(spectral->pdev_obj);
2009 			psoc = wlan_pdev_get_psoc(spectral->pdev_obj);
2010 			qdf_assert_always(psoc);
2011 
2012 			params.agc_total_gain_sec80 =
2013 				sscan_report_fields.sscan_agc_total_gain;
2014 			params.gainchange_sec80 =
2015 					sscan_report_fields.sscan_gainchange;
2016 			params.raw_timestamp_sec80 = p_sfft->timestamp;
2017 			params.rssi_sec80 = rssi;
2018 			params.noise_floor_sec80    =
2019 				report->noisefloor[chn_idx_lowest_enabled];
2020 			params.max_mag_sec80        = p_sfft->fft_peak_mag;
2021 			params.datalen = fft_hdr_length * 2;
2022 			params.datalen_sec80 = fft_hdr_length * 2;
2023 
2024 			marker = &spectral->rparams.marker[spectral_mode];
2025 			qdf_assert_always(marker->is_valid);
2026 			params.bin_pwr_data = temp +
2027 				marker->start_pri80 * fft_bin_size;
2028 			params.pwr_count = marker->num_pri80;
2029 			params.bin_pwr_data_sec80 = temp +
2030 				marker->start_sec80 * fft_bin_size;
2031 			params.pwr_count_sec80 = marker->num_sec80;
2032 			if (spectral->ch_width[spectral_mode] ==
2033 			    CH_WIDTH_80P80MHZ && wlan_psoc_nif_fw_ext_cap_get(
2034 			    psoc, WLAN_SOC_RESTRICTED_80P80_SUPPORT)) {
2035 				params.bin_pwr_data_5mhz = temp +
2036 					marker->start_5mhz * fft_bin_size;
2037 				params.pwr_count_5mhz = marker->num_5mhz;
2038 			}
2039 		} else {
2040 			params.bin_pwr_data = temp;
2041 			params.pwr_count = fft_bin_count;
2042 			params.datalen = (fft_hdr_length * 4);
2043 		}
2044 
2045 		target_if_spectral_verify_ts(spectral, report->data,
2046 					     params.tstamp);
2047 	} else if (is_secondaryseg_expected(spectral, spectral_mode)) {
2048 		/* RSSI is in 1/2 dBm steps, Covert it to dBm scale */
2049 		rssi = (sscan_report_fields.inband_pwr_db) >> 1;
2050 		params.agc_total_gain_sec80 =
2051 			sscan_report_fields.sscan_agc_total_gain;
2052 		params.gainchange_sec80 = sscan_report_fields.sscan_gainchange;
2053 		params.pri80ind_sec80 = sscan_report_fields.sscan_pri80;
2054 
2055 		/* Process Spectral search FFT report */
2056 		if (target_if_verify_sig_and_tag_gen3(
2057 				spectral, data,
2058 				TLV_TAG_SEARCH_FFT_REPORT_GEN3) != 0) {
2059 			spectral_err_rl("Unexpected tag/sig in sfft, detid= %u",
2060 					detector_id);
2061 			goto fail;
2062 		}
2063 		p_fft_report = (struct spectral_phyerr_fft_report_gen3 *)data;
2064 		fft_hdr_length = p_fft_report->fft_hdr_length * 4;
2065 		if (fft_hdr_length < 16) {
2066 			spectral_err("Wrong TLV length %u, detector id = %u",
2067 				     fft_hdr_length, detector_id);
2068 			goto fail;
2069 		}
2070 
2071 		report_len     = (fft_hdr_length + 8);
2072 
2073 		target_if_process_sfft_report_gen3(p_fft_report, p_sfft);
2074 		/* It is expected to have same detector id for
2075 		 * summary and fft report
2076 		 */
2077 		if (detector_id != p_sfft->fft_detector_id) {
2078 			spectral_err_rl
2079 				("Different detid in ssummary(%u) and sfft(%u)",
2080 				 detector_id, p_sfft->fft_detector_id);
2081 			goto fail;
2082 		}
2083 
2084 		if (detector_id > spectral->rparams.num_spectral_detectors) {
2085 			spectral->diag_stats.spectral_invalid_detector_id++;
2086 			spectral_err("Invalid detector id %u, expected is 1",
2087 				     detector_id);
2088 			goto fail;
2089 		}
2090 		params.smode = spectral_mode;
2091 
2092 		fft_bin_count = target_if_spectral_get_bin_count_after_len_adj(
2093 			fft_hdr_length - spectral->rparams.fft_report_hdr_len,
2094 			spectral->params[spectral_mode].ss_rpt_mode,
2095 			&spectral->len_adj_swar, &fft_bin_size);
2096 		params.raw_timestamp_sec80 = p_sfft->timestamp;
2097 
2098 		/* Take care of state transitions for 160 MHz and 80p80 */
2099 		if (is_ch_width_160_or_80p80(spectral->ch_width
2100 		    [spectral_mode]) && spectral->rparams.
2101 		    fragmentation_160[spectral_mode]) {
2102 			ret = target_if_160mhz_delivery_state_change(
2103 					spectral, spectral_mode,
2104 					detector_id);
2105 			if (ret != QDF_STATUS_SUCCESS)
2106 				goto fail;
2107 		}
2108 
2109 		if (spectral_debug_level & (DEBUG_SPECTRAL2 | DEBUG_SPECTRAL4))
2110 			target_if_dump_fft_report_gen3(spectral, spectral_mode,
2111 						       p_fft_report, p_sfft);
2112 
2113 		params.rssi_sec80 = rssi;
2114 
2115 		vdev = target_if_spectral_get_vdev(spectral);
2116 		if (!vdev) {
2117 			spectral_info("First vdev is NULL");
2118 			reset_160mhz_delivery_state_machine
2119 						(spectral, spectral_mode);
2120 			return -EPERM;
2121 		}
2122 		vdev_rxchainmask = wlan_vdev_mlme_get_rxchainmask(vdev);
2123 		QDF_ASSERT(vdev_rxchainmask != 0);
2124 		wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
2125 
2126 		chn_idx_lowest_enabled =
2127 		target_if_spectral_get_lowest_chn_idx(vdev_rxchainmask);
2128 		if (chn_idx_lowest_enabled >= DBR_MAX_CHAINS) {
2129 			spectral_err("Invalid chain index");
2130 			goto fail;
2131 		}
2132 
2133 		/* Need to change this as per FW team's inputs */
2134 		params.noise_floor_sec80    =
2135 			report->noisefloor[chn_idx_lowest_enabled];
2136 
2137 		params.max_mag_sec80        = p_sfft->fft_peak_mag;
2138 		/* params.max_index_sec80      = p_sfft->peak_inx; */
2139 		/* XXX Does this definition of datalen *still hold? */
2140 		params.datalen_sec80        = fft_hdr_length * 4;
2141 		params.pwr_count_sec80      = fft_bin_count;
2142 		params.bin_pwr_data_sec80   =
2143 			(uint8_t *)((uint8_t *)p_fft_report +
2144 			 SPECTRAL_FFT_BINS_POS);
2145 	} else {
2146 		spectral_err("Spectral state machine in undefined state");
2147 		goto fail;
2148 	}
2149 
2150 	target_if_spectral_check_buffer_poisoning(spectral, report,
2151 						  fft_bin_count, spectral_mode);
2152 	qdf_mem_copy(&params.classifier_params,
2153 		     &spectral->classifier_params,
2154 		     sizeof(struct spectral_classifier_params));
2155 
2156 	target_if_spectral_log_SAMP_param(&params);
2157 	target_if_spectral_create_samp_msg(spectral, &params);
2158 
2159 	return 0;
2160  fail:
2161 	spectral_err_rl("Error while processing Spectral report");
2162 	if (spectral_mode != SPECTRAL_SCAN_MODE_INVALID)
2163 		reset_160mhz_delivery_state_machine(spectral, spectral_mode);
2164 	return -EPERM;
2165 }
2166 
2167 int target_if_spectral_process_report_gen3(
2168 	struct wlan_objmgr_pdev *pdev,
2169 	void *buf)
2170 {
2171 	int ret = 0;
2172 	struct direct_buf_rx_data *payload = buf;
2173 	struct target_if_spectral *spectral;
2174 	struct spectral_report report;
2175 
2176 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
2177 	if (!spectral) {
2178 		spectral_err("Spectral target object is null");
2179 		return -EINVAL;
2180 	}
2181 
2182 	report.data = payload->vaddr;
2183 	if (payload->meta_data_valid) {
2184 		qdf_mem_copy(report.noisefloor, payload->meta_data.noisefloor,
2185 			     qdf_min(sizeof(report.noisefloor),
2186 				     sizeof(payload->meta_data.noisefloor)));
2187 		report.reset_delay = payload->meta_data.reset_delay;
2188 		report.cfreq1 = payload->meta_data.cfreq1;
2189 		report.cfreq2 = payload->meta_data.cfreq2;
2190 		report.ch_width = payload->meta_data.ch_width;
2191 	}
2192 
2193 	if (spectral_debug_level & (DEBUG_SPECTRAL2 | DEBUG_SPECTRAL4)) {
2194 		spectral_debug("Printing the spectral phyerr buffer for debug");
2195 		spectral_debug("Datalength of buffer = 0x%zx(%zd) bufptr = 0x%pK",
2196 			       payload->dbr_len,
2197 			       payload->dbr_len,
2198 			       payload->vaddr);
2199 		target_if_spectral_hexdump((unsigned char *)payload->vaddr,
2200 					   1024);
2201 	}
2202 
2203 	ret = target_if_consume_spectral_report_gen3(spectral, &report);
2204 
2205 	if (spectral_debug_level & DEBUG_SPECTRAL4)
2206 		spectral_debug_level = DEBUG_SPECTRAL;
2207 
2208 	return ret;
2209 }
2210 #else
2211 int target_if_spectral_process_report_gen3(
2212 	struct wlan_objmgr_pdev *pdev,
2213 	void *buf)
2214 {
2215 	spectral_err("Direct dma support is not enabled");
2216 	return -EINVAL;
2217 }
2218 #endif
2219 qdf_export_symbol(target_if_spectral_process_report_gen3);
2220 /* END of spectral GEN III HW specific functions */
2221 
2222 #endif  /* WLAN_CONV_SPECTRAL_ENABLE */
2223