xref: /wlan-dirver/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_process_radarevent.c (revision 901120c066e139c7f8a2c8e4820561fdd83c67ef)
1 /*
2  * Copyright (c) 2013, 2016-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
4  * Copyright (c) 2002-2010, Atheros Communications Inc.
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /**
20  * DOC: This contains the functionality to process the radar event generated
21  * for a pulse. This will group together pulses and call various detection
22  * functions to figure out whether a valid radar has been detected.
23  */
24 
25 #include "../dfs.h"
26 #include "../dfs_zero_cac.h"
27 #include "../dfs_channel.h"
28 #include "../dfs_internal.h"
29 #include "../dfs_process_radar_found_ind.h"
30 #include <wlan_objmgr_vdev_obj.h>
31 #include "wlan_dfs_utils_api.h"
32 #include "wlan_dfs_lmac_api.h"
33 #include "../dfs_partial_offload_radar.h"
34 #include "../dfs_confirm_radar.h"
35 
36 #ifdef DFS_FCC_TYPE4_DURATION_CHECK
37 #define DFS_WAR_30_MHZ_SEPARATION   30
38 #define DFS_WAR_PEAK_INDEX_ZERO 0
39 #define DFS_TYPE4_WAR_PULSE_DURATION_LOWER_LIMIT 11
40 #define DFS_TYPE4_WAR_PULSE_DURATION_UPPER_LIMIT 33
41 #define DFS_TYPE4_WAR_PRI_LOWER_LIMIT 200
42 #define DFS_TYPE4_WAR_PRI_UPPER_LIMIT 500
43 #define DFS_TYPE4_WAR_VALID_PULSE_DURATION 12
44 #endif
45 
46 #define FREQ_5500_MHZ  5500
47 #define FREQ_5500_MHZ       5500
48 
49 #define DFS_MAX_FREQ_SPREAD            (1375 * 1)
50 #define DFS_LARGE_PRI_MULTIPLIER       4
51 #define DFS_W53_DEFAULT_PRI_MULTIPLIER 2
52 #define DFS_BIG_SIDX          10000
53 
54 static char debug_dup[33];
55 static int debug_dup_cnt;
56 
57 /**
58  * dfs_process_pulse_dur() - Process pulse duration.
59  * @dfs: Pointer to wlan_dfs structure.
60  * @re_dur: Duration.
61  *
62  * Convert the hardware provided duration to TSF ticks (usecs) taking the clock
63  * (fast or normal) into account. Legacy (pre-11n, Owl, Sowl, Howl) operate
64  * 5GHz using a 40MHz clock.  Later 11n chips (Merlin, Osprey, etc) operate
65  * 5GHz using a 44MHz clock, so the reported pulse durations are different.
66  * Peregrine reports the pulse duration in microseconds regardless of the
67  * operating mode. (XXX TODO: verify this, obviously.)
68  *
69  * The hardware returns the duration in a variety of formats,
70  * so it's converted from the hardware format to TSF (usec)
71  * values here.
72  * XXX TODO: this should really be done when the PHY error
73  * is processed, rather than way out here..
74  *
75  *
76  * Return: Returns the duration.
77  */
78 static inline uint8_t dfs_process_pulse_dur(struct wlan_dfs *dfs,
79 		uint8_t re_dur)
80 {
81 	/*
82 	 * Short pulses are sometimes returned as having a duration of 0,
83 	 * so round those up to 1.
84 	 * XXX This holds true for BB TLV chips too, right?
85 	 */
86 	if (re_dur == 0)
87 		return 1;
88 
89 	/*
90 	 * For BB TLV chips, the hardware always returns microsecond pulse
91 	 * durations.
92 	 */
93 	if (dfs->dfs_caps.wlan_chip_is_bb_tlv)
94 		return re_dur;
95 
96 	/*
97 	 * This is for 11n and legacy chips, which may or may not use the 5GHz
98 	 * fast clock mode.
99 	 */
100 	/* Convert 0.8us durations to TSF ticks (usecs) */
101 	return (uint8_t)dfs_round((int32_t)((dfs->dur_multiplier)*re_dur));
102 }
103 
104 #ifdef DFS_FCC_TYPE4_DURATION_CHECK
105 /*
106  * dfs_dur_check() - Modify the pulse duration for FCC Type 4 and JAPAN W56
107  *                   Type 8 radar pulses when the conditions mentioned in the
108  *                   function body are reported in the radar summary report.
109  * @dfs: Pointer to wlan_dfs structure.
110  * @chan: Current  channel.
111  * @re: Pointer to dfs_event.
112  * @diff_ts: timestamp of current pulse - timestamp of last pulse.
113  *
114  * return: Void
115  */
116 static inline void dfs_dur_check(
117 	struct wlan_dfs *dfs,
118 	struct dfs_channel *chan,
119 	struct dfs_event *re,
120 	uint32_t diff_ts)
121 {
122 	if ((dfs->dfsdomain == DFS_FCC_DOMAIN ||
123 	     dfs->dfsdomain == DFS_MKK4_DOMAIN ||
124 		 dfs->dfsdomain == DFS_MKKN_DOMAIN) &&
125 	    ((chan->dfs_ch_flags & WLAN_CHAN_VHT80) == WLAN_CHAN_VHT80) &&
126 	    (DFS_DIFF(chan->dfs_ch_freq, chan->dfs_ch_mhz_freq_seg1) ==
127 	    DFS_WAR_30_MHZ_SEPARATION) &&
128 	    re->re_sidx == DFS_WAR_PEAK_INDEX_ZERO &&
129 	    (re->re_dur > DFS_TYPE4_WAR_PULSE_DURATION_LOWER_LIMIT &&
130 	    re->re_dur < DFS_TYPE4_WAR_PULSE_DURATION_UPPER_LIMIT) &&
131 	    (diff_ts > DFS_TYPE4_WAR_PRI_LOWER_LIMIT &&
132 	    diff_ts < DFS_TYPE4_WAR_PRI_UPPER_LIMIT)) {
133 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
134 			  "chan flags=%llu, Pri Chan %d MHz center %d MHZ",
135 			  chan->dfs_ch_flags,
136 			  chan->dfs_ch_freq, chan->dfs_ch_mhz_freq_seg1);
137 
138 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
139 			  "Report Peak Index = %d,re.re_dur = %d,diff_ts = %d",
140 			  re->re_sidx, re->re_dur, diff_ts);
141 
142 		re->re_dur = DFS_TYPE4_WAR_VALID_PULSE_DURATION;
143 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
144 			  "Modifying the pulse duration to %d", re->re_dur);
145 	}
146 }
147 #else
148 static inline void dfs_dur_check(
149 	struct wlan_dfs *dfs,
150 	struct dfs_channel *chan,
151 	struct dfs_event *re,
152 	uint32_t diff_ts)
153 {
154 }
155 #endif
156 
157 /*
158  * dfs_print_radar_events() - Prints the Radar events.
159  * @dfs: Pointer to wlan_dfs structure.
160  */
161 static void dfs_print_radar_events(struct wlan_dfs *dfs)
162 {
163 	int i;
164 
165 	dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS, "#Phyerr=%d, #false detect=%d, #queued=%d",
166 		  dfs->dfs_phyerr_count, dfs->dfs_phyerr_reject_count,
167 		  dfs->dfs_phyerr_queued_count);
168 
169 	dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs_phyerr_freq_min=%d, dfs_phyerr_freq_max=%d",
170 		  dfs->dfs_phyerr_freq_min, dfs->dfs_phyerr_freq_max);
171 
172 	dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
173 		  "Total radar events detected=%d, entries in the radar queue follows:",
174 		  dfs->dfs_event_log_count);
175 
176 	for (i = 0; (i < DFS_EVENT_LOG_SIZE) && (i < dfs->dfs_event_log_count);
177 			i++) {
178 		dfs_debug(dfs, WLAN_DEBUG_DFS,
179 			  "ts=%llu diff_ts=%u rssi=%u dur=%u, is_chirp=%d, seg_id=%d, sidx=%d, freq_offset=%d.%dMHz, peak_mag=%d, total_gain=%d, mb_gain=%d, relpwr_db=%d, delta_diff=%d, delta_peak=%d, psidx_diff=%d",
180 			  dfs->radar_log[i].ts, dfs->radar_log[i].diff_ts,
181 			  dfs->radar_log[i].rssi, dfs->radar_log[i].dur,
182 			  dfs->radar_log[i].is_chirp, dfs->radar_log[i].seg_id,
183 			  dfs->radar_log[i].sidx,
184 			  (int)dfs->radar_log[i].freq_offset_khz / 1000,
185 			  (int)abs(dfs->radar_log[i].freq_offset_khz) % 1000,
186 			  dfs->radar_log[i].peak_mag,
187 			  dfs->radar_log[i].total_gain,
188 			  dfs->radar_log[i].mb_gain,
189 			  dfs->radar_log[i].relpwr_db,
190 			  dfs->radar_log[i].delta_diff,
191 			  dfs->radar_log[i].delta_peak,
192 			  dfs->radar_log[i].psidx_diff);
193 	}
194 	dfs->dfs_event_log_count = 0;
195 	dfs->dfs_phyerr_count = 0;
196 	dfs->dfs_phyerr_reject_count = 0;
197 	dfs->dfs_phyerr_queued_count = 0;
198 	dfs->dfs_phyerr_freq_min = 0x7fffffff;
199 	dfs->dfs_phyerr_freq_max = 0;
200 }
201 
202 #ifndef CONFIG_EXT_RADAR_PROCESS
203 /**
204  * dfs_is_real_radar() - This function checks for fractional PRI and jitter in
205  * sidx index to determine if the radar is real or not.
206  * @dfs: Pointer to dfs structure.
207  * @rf: Pointer to dfs_filter structure.
208  * @ext_chan_flag: ext chan flags.
209  *
210  * Return : true if real RADAR else false.
211  */
212 static bool dfs_is_real_radar(struct wlan_dfs *dfs,
213 			      struct dfs_filter *rf,
214 			      int ext_chan_flag)
215 {
216 	int i = 0;
217 	int index;
218 	struct dfs_delayline *dl = &rf->rf_dl;
219 	struct dfs_delayelem *de;
220 	uint64_t target_ts = 0;
221 	struct dfs_pulseline *pl;
222 	int start_index = 0, current_index, next_index;
223 	unsigned char scores[FRAC_PRI_SCORE_ARRAY_SIZE];
224 	uint32_t pri_margin;
225 	uint64_t this_diff_ts;
226 	uint32_t search_bin;
227 
228 	unsigned char max_score = 0;
229 	int max_score_index = 0;
230 
231 	pl = dfs->pulses;
232 
233 	OS_MEMZERO(scores, sizeof(scores));
234 	scores[0] = rf->rf_threshold;
235 
236 	pri_margin = dfs_get_pri_margin(dfs, ext_chan_flag,
237 			(rf->rf_patterntype == 1));
238 
239 	/*
240 	 * Look for the entry that matches dl_seq_num_second.
241 	 * we need the time stamp and diff_ts from there.
242 	 */
243 
244 	for (i = 0; i < dl->dl_numelems; i++) {
245 		index = (dl->dl_firstelem + i) & DFS_MAX_DL_MASK;
246 		de = &dl->dl_elems[index];
247 		if (dl->dl_seq_num_second == de->de_seq_num)
248 			target_ts = de->de_ts - de->de_time;
249 	}
250 
251 	if (dfs->dfs_debug_mask & WLAN_DEBUG_DFS2) {
252 		dfs_print_delayline(dfs, &rf->rf_dl);
253 
254 		dfs_debug(dfs, WLAN_DEBUG_DFS2, "Pulse Line");
255 		for (i = 0; i < pl->pl_numelems; i++) {
256 			index =  (pl->pl_firstelem + i) &
257 				DFS_MAX_PULSE_BUFFER_MASK;
258 			dfs_debug(dfs, WLAN_DEBUG_DFS2,
259 					"Elem %u: ts=%llu dur=%u, seq_num=%d, delta_peak=%d, psidx_diff=%d\n",
260 					i, pl->pl_elems[index].p_time,
261 					pl->pl_elems[index].p_dur,
262 					pl->pl_elems[index].p_seq_num,
263 					pl->pl_elems[index].p_delta_peak,
264 					pl->pl_elems[index].p_psidx_diff);
265 		}
266 	}
267 
268 	/*
269 	 * Walk through the pulse line and find pulse with target_ts.
270 	 * Then continue until we find entry with seq_number dl_seq_num_stop.
271 	 */
272 
273 	for (i = 0; i < pl->pl_numelems; i++) {
274 		index =  (pl->pl_firstelem + i) & DFS_MAX_PULSE_BUFFER_MASK;
275 		if (pl->pl_elems[index].p_time == target_ts) {
276 			dl->dl_seq_num_start = pl->pl_elems[index].p_seq_num;
277 			start_index = index; /* save for future use */
278 		}
279 	}
280 
281 	dfs_debug(dfs, WLAN_DEBUG_DFS2,
282 		  "target_ts=%llu, dl_seq_num_start=%d, dl_seq_num_second=%d, dl_seq_num_stop=%d",
283 		  target_ts, dl->dl_seq_num_start,
284 		  dl->dl_seq_num_second, dl->dl_seq_num_stop);
285 
286 	current_index = start_index;
287 	while (pl->pl_elems[current_index].p_seq_num < dl->dl_seq_num_stop) {
288 		next_index = (current_index + 1) & DFS_MAX_PULSE_BUFFER_MASK;
289 		this_diff_ts = pl->pl_elems[next_index].p_time -
290 			pl->pl_elems[current_index].p_time;
291 
292 		/* Now update the score for this diff_ts */
293 		for (i = 1; i < FRAC_PRI_SCORE_ARRAY_SIZE; i++) {
294 			search_bin = dl->dl_search_pri / (i + 1);
295 
296 			/*
297 			 * We do not give score to PRI that is lower then the
298 			 * limit.
299 			 */
300 			if (search_bin < dfs->dfs_lowest_pri_limit)
301 				break;
302 
303 			/*
304 			 * Increment the score if this_diff_ts belongs to this
305 			 * search_bin +/- margin.
306 			 */
307 			if ((this_diff_ts >= (search_bin - pri_margin)) &&
308 					(this_diff_ts <=
309 					 (search_bin + pri_margin))) {
310 				/*increment score */
311 				scores[i]++;
312 			}
313 		}
314 		current_index = next_index;
315 	}
316 
317 	for (i = 0; i < FRAC_PRI_SCORE_ARRAY_SIZE; i++)
318 		if (scores[i] > max_score) {
319 			max_score = scores[i];
320 			max_score_index = i;
321 		}
322 
323 	if (max_score_index != 0) {
324 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
325 			  "Rejecting Radar since Fractional PRI detected: searchpri=%d, threshold=%d, fractional PRI=%d, Fractional PRI score=%d",
326 			  dl->dl_search_pri, scores[0],
327 			  dl->dl_search_pri/(max_score_index + 1),
328 			  max_score);
329 		return 0;
330 	}
331 
332 
333 	/* Check for frequency spread */
334 	if (dl->dl_min_sidx > pl->pl_elems[start_index].p_sidx)
335 		dl->dl_min_sidx = pl->pl_elems[start_index].p_sidx;
336 
337 	if (dl->dl_max_sidx < pl->pl_elems[start_index].p_sidx)
338 		dl->dl_max_sidx = pl->pl_elems[start_index].p_sidx;
339 
340 	if ((dl->dl_max_sidx - dl->dl_min_sidx) > rf->rf_sidx_spread) {
341 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
342 			  "Rejecting Radar since frequency spread is too large : min_sidx=%d, max_sidx=%d, rf_sidx_spread=%d",
343 			  dl->dl_min_sidx, dl->dl_max_sidx,
344 			  rf->rf_sidx_spread);
345 		return 0;
346 	}
347 
348 	if ((rf->rf_check_delta_peak) &&
349 			((dl->dl_delta_peak_match_count +
350 			dl->dl_psidx_diff_match_count - 1) <
351 			rf->rf_threshold)) {
352 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
353 			  "Rejecting Radar since delta peak values are invalid : dl_delta_peak_match_count=%d, dl_psidx_diff_match_count=%d, rf_threshold=%d",
354 			  dl->dl_delta_peak_match_count,
355 			  dl->dl_psidx_diff_match_count,
356 			  rf->rf_threshold);
357 		return 0;
358 	}
359 	dfs_debug(dfs, WLAN_DEBUG_DFS_FALSE_DET,
360 		  "dl->dl_min_sidx: %d, dl->dl_max_sidx: %d",
361 		  dl->dl_min_sidx, dl->dl_max_sidx);
362 
363 	dfs->dfs_freq_offset = DFS_SIDX_TO_FREQ_OFFSET((dl->dl_min_sidx +
364 							dl->dl_max_sidx) / 2);
365 	return 1;
366 }
367 #endif /* CONFIG_EXT_RADAR_PROCESS */
368 
369 /*
370  * dfs_reject_on_pri() - Rejecting on individual filter based on min PRI .
371  * @dfs: Pointer to wlan_dfs structure.
372  * @rf: Pointer to dfs_filter structure.
373  * @deltaT: deltaT value.
374  * @this_ts: Timestamp.
375  */
376 static inline bool dfs_reject_on_pri(
377 		struct wlan_dfs *dfs,
378 		struct dfs_filter *rf,
379 		uint64_t deltaT,
380 		uint64_t this_ts)
381 {
382 	if ((deltaT < rf->rf_minpri) && (deltaT != 0)) {
383 		/* Second line of PRI filtering. */
384 		dfs_debug(dfs, WLAN_DEBUG_DFS2,
385 				"filterID %d : Rejecting on individual filter min PRI deltaT=%lld rf->rf_minpri=%u",
386 				rf->rf_pulseid, (uint64_t)deltaT,
387 				rf->rf_minpri);
388 		return 1;
389 	}
390 
391 	if (rf->rf_ignore_pri_window > 0) {
392 		if (deltaT < rf->rf_minpri) {
393 			dfs_debug(dfs, WLAN_DEBUG_DFS2,
394 					"filterID %d : Rejecting on individual filter max PRI deltaT=%lld rf->rf_minpri=%u",
395 					rf->rf_pulseid, (uint64_t)deltaT,
396 					rf->rf_minpri);
397 			/* But update the last time stamp. */
398 			rf->rf_dl.dl_last_ts = this_ts;
399 			return 1;
400 		}
401 	} else {
402 		/*
403 		 * The HW may miss some pulses especially with
404 		 * high channel loading. This is true for Japan
405 		 * W53 where channel loaoding is 50%. Also for
406 		 * ETSI where channel loading is 30% this can
407 		 * be an issue too. To take care of missing
408 		 * pulses, we introduce pri_margin multiplie.
409 		 * This is normally 2 but can be higher for W53.
410 		 */
411 
412 		if ((deltaT > (dfs->dfs_pri_multiplier * rf->rf_maxpri)) ||
413 				(deltaT < rf->rf_minpri)) {
414 			dfs_debug(dfs, WLAN_DEBUG_DFS2,
415 					"filterID %d : Rejecting on individual filter max PRI deltaT=%lld rf->rf_minpri=%u",
416 					rf->rf_pulseid, (uint64_t) deltaT,
417 					rf->rf_minpri);
418 			/* But update the last time stamp. */
419 			rf->rf_dl.dl_last_ts = this_ts;
420 			return 1;
421 		}
422 	}
423 
424 	return 0;
425 }
426 
427 /**
428  * dfs_confirm_radar_check() - Do additioal check to conirm radar except for
429  * the staggered, chirp FCC Bin 5, frequency hopping indicated by
430  * rf_patterntype == 1.
431  * @dfs: Pointer to wlan_dfs structure.
432  * @rf: Pointer to dfs_filter structure.
433  * @ext_chan_event_flag: Extension channel event flag
434  * @found: Pointer to radar found flag (return value).
435  * @false_radar_found: Pointer to false radar found (return value).
436  */
437 
438 static inline void dfs_confirm_radar_check(
439 		struct wlan_dfs *dfs,
440 		struct dfs_filter *rf,
441 		int ext_chan_event_flag,
442 		int *found,
443 		int *false_radar_found)
444 {
445 	if (rf->rf_patterntype != 1) {
446 		*found = (int)dfs_is_real_radar(dfs, rf, ext_chan_event_flag);
447 		*false_radar_found = (*found == 1) ? 0 : 1;
448 	}
449 }
450 
451 /*
452  * __dfs_process_radarevent() - Continuation of process a radar event function.
453  * @dfs: Pointer to wlan_dfs structure.
454  * @ft: Pointer to dfs_filtertype structure.
455  * @re: Pointer to dfs_event structure.
456  * @this_ts: Timestamp.
457  *
458  * There is currently no way to specify that a radar event has occurred on
459  * a specific channel, so the current methodology is to mark both the pri
460  * and ext channels as being unavailable.  This should be fixed for 802.11ac
461  * or we'll quickly run out of valid channels to use.
462  *
463  * Return: If a radar event is found, return 1.  Otherwise, return 0.
464  */
465 static void __dfs_process_radarevent(struct wlan_dfs *dfs,
466 				     struct dfs_filtertype *ft,
467 				     struct dfs_event *re,
468 				     uint64_t this_ts,
469 				     int *found,
470 				     int *false_radar_found)
471 {
472 	int p;
473 	uint64_t deltaT = 0;
474 	int ext_chan_event_flag = 0;
475 	struct dfs_filter *rf = NULL;
476 	int8_t ori_rf_check_delta_peak = 0;
477 
478 	for (p = 0, *found = 0; (p < ft->ft_numfilters) &&
479 			(!(*found)) && !(*false_radar_found); p++) {
480 		rf = ft->ft_filters[p];
481 		if ((re->re_dur >= rf->rf_mindur) &&
482 				(re->re_dur <= rf->rf_maxdur)) {
483 			/* The above check is probably not necessary. */
484 			deltaT = (this_ts < rf->rf_dl.dl_last_ts) ?
485 			    (int64_t)((DFS_TSF_WRAP - rf->rf_dl.dl_last_ts) +
486 				    this_ts + 1) :
487 			    this_ts - rf->rf_dl.dl_last_ts;
488 
489 			if (dfs_reject_on_pri(dfs, rf, deltaT, this_ts))
490 				continue;
491 
492 			dfs_add_pulse(dfs, rf, re, deltaT, this_ts);
493 
494 			/*
495 			 * If this is an extension channel event, flag it for
496 			 * false alarm reduction.
497 			 */
498 			if (re->re_chanindex == dfs->dfs_extchan_radindex)
499 				ext_chan_event_flag = 1;
500 
501 			if (rf->rf_patterntype == 2) {
502 				*found = dfs_staggered_check(dfs, rf,
503 					(uint32_t) deltaT, re->re_dur);
504 			} else {
505 				*found = dfs_bin_check(dfs, rf,
506 					(uint32_t) deltaT, re->re_dur,
507 					ext_chan_event_flag);
508 
509 				if (*found &&
510 				    (utils_get_dfsdomain(dfs->dfs_pdev_obj) !=
511 				     DFS_CN_DOMAIN)) {
512 					ori_rf_check_delta_peak =
513 						rf->rf_check_delta_peak;
514 					/*
515 					 * If FW does not send valid psidx_diff
516 					 * Do not do chirp check.
517 					 */
518 					if (rf->rf_check_delta_peak &&
519 						(!(re->re_flags &
520 						DFS_EVENT_VALID_PSIDX_DIFF)))
521 						rf->rf_check_delta_peak = false;
522 					dfs_confirm_radar_check(dfs,
523 							rf, ext_chan_event_flag,
524 							found,
525 							false_radar_found);
526 					rf->rf_check_delta_peak =
527 						ori_rf_check_delta_peak;
528 				}
529 			}
530 
531 			if (dfs->dfs_debug_mask & WLAN_DEBUG_DFS2)
532 				if (rf->rf_patterntype !=
533 						WLAN_DFS_RF_PATTERN_TYPE_1)
534 					dfs_print_delayline(dfs, &rf->rf_dl);
535 
536 			rf->rf_dl.dl_last_ts = this_ts;
537 		}
538 	}
539 
540 	if (*found) {
541 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
542 			  "Found on channel minDur = %d, filterId = %d",
543 			  ft->ft_mindur,
544 			  rf ?  rf->rf_pulseid : -1);
545 	}
546 
547 	return;
548 }
549 
550 /**
551  * dfs_cal_average_radar_parameters() - Calculate the average radar parameters.
552  * @dfs: Pointer to wlan_dfs structure.
553  */
554 #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
555 static void dfs_cal_average_radar_parameters(struct wlan_dfs *dfs)
556 {
557 	int i, count = 0;
558 	u_int32_t total_pri = 0;
559 	u_int32_t total_duration = 0;
560 	u_int32_t total_sidx = 0;
561 
562 	/* Calculating average PRI, Duration, SIDX from
563 	 * the 2nd pulse, ignoring the 1st pulse (radar_log[0]).
564 	 * This is because for the first pulse, the diff_ts will be
565 	 * (0 - current_ts) which will be a huge value.
566 	 * Average PRI computation will be wrong. FW returns a
567 	 * failure test result as PRI does not match their expected
568 	 * value.
569 	 */
570 
571 	for (i = 1; (i < DFS_EVENT_LOG_SIZE) && (i < dfs->dfs_event_log_count);
572 			i++) {
573 		total_pri +=  dfs->radar_log[i].diff_ts;
574 		total_duration += dfs->radar_log[i].dur;
575 		total_sidx +=  dfs->radar_log[i].sidx;
576 		count++;
577 	}
578 
579 	if (count > 0) {
580 		dfs->dfs_average_pri = total_pri / count;
581 		dfs->dfs_average_duration = total_duration / count;
582 		dfs->dfs_average_sidx = total_sidx / count;
583 
584 		dfs_debug(dfs, WLAN_DEBUG_DFS2,
585 			  "Avg.PRI =%u, Avg.duration =%u Avg.sidx =%u",
586 			  dfs->dfs_average_pri,
587 			  dfs->dfs_average_duration,
588 			  dfs->dfs_average_sidx);
589 	}
590 }
591 #else
592 static void dfs_cal_average_radar_parameters(struct wlan_dfs *dfs)
593 {
594 }
595 #endif
596 
597 /**
598  * dfs_radarfound_reset_vars() - Reset dfs variables after radar found
599  * @dfs: Pointer to wlan_dfs structure.
600  * @rs: Pointer to dfs_state.
601  * @chan: Current  channel.
602  * @seg_id: Segment id.
603  */
604 static inline void dfs_radarfound_reset_vars(
605 		struct wlan_dfs *dfs,
606 		struct dfs_state *rs,
607 		struct dfs_channel *chan,
608 		uint8_t seg_id)
609 {
610 	struct dfs_channel *thischan;
611 
612 	/*
613 	 * TODO: Instead of discarding the radar, create a workqueue
614 	 * if the channel change is happening through userspace and
615 	 * process the radar event once the channel change is completed.
616 	 */
617 
618 	/* Collect stats */
619 	dfs->wlan_dfs_stats.num_radar_detects++;
620 	thischan = &rs->rs_chan;
621 	if ((seg_id == SEG_ID_SECONDARY) &&
622 			(dfs_is_precac_timer_running(dfs)))
623 		dfs->is_radar_during_precac = 1;
624 
625 	/*
626 	 * If event log is on then dump the radar event queue on
627 	 * filter match. This can be used to collect information
628 	 * on false radar detection.
629 	 */
630 	if (dfs->dfs_event_log_on) {
631 		dfs_cal_average_radar_parameters(dfs);
632 		dfs_print_radar_events(dfs);
633 	}
634 
635 	dfs_reset_radarq(dfs);
636 	dfs_reset_alldelaylines(dfs);
637 
638 	dfs_debug(dfs, WLAN_DEBUG_DFS1,
639 			"Primary channel freq = %u flags=0x%x",
640 			chan->dfs_ch_freq, chan->dfs_ch_flagext);
641 
642 	if (chan->dfs_ch_freq != thischan->dfs_ch_freq)
643 		dfs_debug(dfs, WLAN_DEBUG_DFS1,
644 				"Ext channel freq = %u flags=0x%x",
645 				thischan->dfs_ch_freq,
646 				thischan->dfs_ch_flagext);
647 
648 	dfs->dfs_phyerr_freq_min = 0x7fffffff;
649 	dfs->dfs_phyerr_freq_max = 0;
650 	dfs->dfs_phyerr_w53_counter = 0;
651 
652 	if (seg_id == SEG_ID_SECONDARY) {
653 		dfs->wlan_dfs_stats.num_seg_two_radar_detects++;
654 		dfs->is_radar_found_on_secondary_seg = 1;
655 	}
656 }
657 
658 /*
659  * dfs_print_radar_found_freq() - Print radar found frequency.
660  * @dfs: Pointer to wlan_dfs.
661  */
662 #ifdef CONFIG_CHAN_FREQ_API
663 static void dfs_print_radar_found_freq(struct wlan_dfs *dfs)
664 {
665 	dfs_debug(dfs, WLAN_DEBUG_DFS,
666 		  "bangradar on 2nd segment cfreq = %u",
667 		  dfs->dfs_precac_secondary_freq_mhz);
668 }
669 #endif
670 
671 /**
672  * dfs_handle_bangradar - Handle the case of bangradar
673  * @dfs: Pointer to wlan_dfs structure.
674  * @chan: Current channel.
675  * @rs: Pointer to dfs_state.
676  * Return: if bangradar then  return 1.  Otherwise, return 0.
677  */
678 static inline int dfs_handle_bangradar(
679 	struct wlan_dfs *dfs,
680 	struct dfs_channel *chan,
681 	struct dfs_state **rs,
682 	uint8_t *seg_id,
683 	int *retval)
684 {
685 
686 	if (dfs->dfs_bangradar_type) {
687 		if (dfs->dfs_bangradar_type >= DFS_INVALID_BANGRADAR_TYPE) {
688 			dfs_debug(dfs, WLAN_DEBUG_DFS,
689 				  "Invalid bangradar type");
690 			return 1;
691 		}
692 		/* All bangradars are processed similarly.
693 		 * arguments for the bangradar are already stored in
694 		 * respective dfs structures.
695 		 */
696 
697 		*rs = &dfs->dfs_radar[dfs->dfs_curchan_radindex];
698 		if (dfs->dfs_seg_id == SEG_ID_SECONDARY) {
699 			if (dfs_is_precac_timer_running(dfs) ||
700 			    WLAN_IS_CHAN_11AC_VHT160(chan) ||
701 			    WLAN_IS_CHAN_11AC_VHT80_80(chan)) {
702 				dfs->is_radar_found_on_secondary_seg = 1;
703 				dfs_print_radar_found_freq(dfs);
704 			} else {
705 				dfs_debug(dfs, WLAN_DEBUG_DFS,
706 					  "No second segment");
707 				return 1;
708 			}
709 		}
710 		*seg_id = dfs->dfs_seg_id;
711 		dfs_debug(dfs, WLAN_DEBUG_DFS, "bangradar %d",
712 			  dfs->dfs_bangradar_type);
713 		*retval = 1;
714 		return 1;
715 	}
716 	return 0;
717 }
718 
719 /**
720  * dfs_process_w53_pulses() - Prrocess w53 pulses
721  * @dfs: Pointer to wlan_dfs structure.
722  *
723  * For chips that support frequency information, we can relax PRI
724  * restriction if the frequency spread is narrow.
725  */
726 static inline void dfs_process_w53_pulses(
727 		struct wlan_dfs *dfs)
728 {
729 	if ((dfs->dfs_phyerr_freq_max - dfs->dfs_phyerr_freq_min) <
730 			DFS_MAX_FREQ_SPREAD)
731 		dfs->dfs_pri_multiplier = DFS_LARGE_PRI_MULTIPLIER;
732 
733 	dfs_debug(dfs, WLAN_DEBUG_DFS1,
734 			"w53_counter=%d, freq_max=%d, freq_min=%d, pri_multiplier=%d",
735 			 dfs->dfs_phyerr_w53_counter,
736 			dfs->dfs_phyerr_freq_max, dfs->dfs_phyerr_freq_min,
737 			dfs->dfs_pri_multiplier);
738 
739 	dfs->dfs_phyerr_freq_min = 0x7fffffff;
740 	dfs->dfs_phyerr_freq_max = 0;
741 }
742 
743 /**
744  * dfs_handle_missing_pulses - Handle the case of missing pulses
745  * @dfs: Pointer to wlan_dfs structure.
746  * @chan: Current channel.
747  *
748  * The HW may miss some pulses especially with high channel loading.
749  * This is true for Japan W53 where channel loaoding is 50%. Also
750  * for ETSI where channel loading is 30% this can be an issue too.
751  * To take care of missing pulses, we introduce pri_margin multiplie.
752  * This is normally 2 but can be higher for W53.
753  * Return: If not enough pulses return 0.  Otherwise, return 1.
754  */
755 static inline int dfs_handle_missing_pulses(
756 		struct wlan_dfs *dfs,
757 		struct dfs_channel *chan)
758 {
759 	if ((dfs->dfsdomain  == DFS_MKK4_DOMAIN ||
760 	     dfs->dfsdomain == DFS_MKKN_DOMAIN) &&
761 			(dfs->dfs_caps.wlan_chip_is_bb_tlv) &&
762 			(chan->dfs_ch_freq < FREQ_5500_MHZ)) {
763 		dfs->dfs_pri_multiplier = DFS_W53_DEFAULT_PRI_MULTIPLIER;
764 		/*
765 		 * Do not process W53 pulses unless we have a minimum number
766 		 * of them.
767 		 */
768 		if (dfs->dfs_phyerr_w53_counter >= 5)
769 			dfs_process_w53_pulses(dfs);
770 		else
771 			return 0;
772 	}
773 
774 	dfs_debug(dfs, WLAN_DEBUG_DFS1, "pri_multiplier=%d",
775 			 dfs->dfs_pri_multiplier);
776 
777 	return 1;
778 }
779 
780 /**
781  * dfs_is_radarq_empty - check if radarq is empty
782  * @dfs: Pointer to wlan_dfs structure.
783  * @empty: Pointer to empty
784  */
785 static inline void dfs_is_radarq_empty(
786 		struct wlan_dfs *dfs,
787 		int *empty)
788 {
789 	WLAN_DFSQ_LOCK(dfs);
790 	*empty = STAILQ_EMPTY(&(dfs->dfs_radarq));
791 	WLAN_DFSQ_UNLOCK(dfs);
792 }
793 
794 /**
795  * dfs_remove_event_from_radarq - remove event from radarq
796  * @dfs: Pointer to wlan_dfs structure.
797  * @event: Double pointer to the event structure
798  */
799 static inline void dfs_remove_event_from_radarq(
800 		struct wlan_dfs *dfs,
801 		struct dfs_event **event)
802 {
803 	WLAN_DFSQ_LOCK(dfs);
804 	*event = STAILQ_FIRST(&(dfs->dfs_radarq));
805 	if (*event)
806 		STAILQ_REMOVE_HEAD(&(dfs->dfs_radarq), re_list);
807 	WLAN_DFSQ_UNLOCK(dfs);
808 }
809 
810 /**
811  * dfs_return_event_to_eventq - return event to eventq
812  * @dfs: Pointer to wlan_dfs structure.
813  * @event: Pointer to the event structure
814  */
815 static inline void dfs_return_event_to_eventq(
816 		struct wlan_dfs *dfs,
817 		struct dfs_event *event)
818 {
819 	qdf_mem_zero(event, sizeof(struct dfs_event));
820 	WLAN_DFSEVENTQ_LOCK(dfs);
821 	STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), event, re_list);
822 	WLAN_DFSEVENTQ_UNLOCK(dfs);
823 }
824 
825 /**
826  * dfs_log_event - log dfs event
827  * @dfs: Pointer to wlan_dfs structure.
828  * @re:  Pointer to dfs_event re
829  * @this_ts: Current time stamp 64bit
830  * @diff_ts: Difference between 2 timestamps 32bit
831  * @index: Index value.
832  */
833 static inline void dfs_log_event(
834 		struct wlan_dfs *dfs,
835 		struct dfs_event *re,
836 		uint64_t this_ts,
837 		uint32_t diff_ts,
838 		uint32_t index)
839 {
840 	uint8_t i;
841 	struct dfs_pulseline *pl = dfs->pulses;
842 
843 	if (dfs->dfs_event_log_on) {
844 		i = dfs->dfs_event_log_count % DFS_EVENT_LOG_SIZE;
845 		dfs->radar_log[i].ts = this_ts;
846 		dfs->radar_log[i].diff_ts = diff_ts;
847 		dfs->radar_log[i].rssi = (*re).re_rssi;
848 		dfs->radar_log[i].dur = (*re).re_dur;
849 		dfs->radar_log[i].seg_id = (*re).re_seg_id;
850 		dfs->radar_log[i].sidx = (*re).re_sidx;
851 		dfs->radar_log[i].freq_offset_khz =
852 			(*re).re_freq_offset_khz;
853 		dfs->radar_log[i].peak_mag = (*re).re_peak_mag;
854 		dfs->radar_log[i].total_gain = (*re).re_total_gain;
855 		dfs->radar_log[i].mb_gain = (*re).re_mb_gain;
856 		dfs->radar_log[i].relpwr_db = (*re).re_relpwr_db;
857 		dfs->radar_log[i].delta_diff = (*re).re_delta_diff;
858 		dfs->radar_log[i].delta_peak = (*re).re_delta_peak;
859 		dfs->radar_log[i].psidx_diff = (*re).re_psidx_diff;
860 		dfs->radar_log[i].is_chirp = DFS_EVENT_NOTCHIRP(re) ?
861 			0 : 1;
862 		dfs->dfs_event_log_count++;
863 	}
864 
865 	dfs->dfs_seq_num++;
866 	pl->pl_elems[index].p_seq_num = dfs->dfs_seq_num;
867 }
868 
869 /**
870  * dfs_check_if_nonbin5 - Check if radar, other than bin5, is found
871  * @dfs: Pointer to wlan_dfs structure.
872  * @re: Pointer to re (radar event)
873  * @rs: Double Pointer to rs (radar state)
874  * @this_ts: Current time stamp 64bit
875  * @diff_ts: Difference between 2 timestamps 32bit
876  * @found: Pointer to found. If radar found or not.
877  * @retval: Pointer to retval(return value).
878  * @false_radar_found: Pointer to false_radar_found(return value).
879  */
880 static inline void dfs_check_if_nonbin5(
881 	struct wlan_dfs *dfs,
882 	struct dfs_event *re,
883 	struct dfs_state **rs,
884 	uint64_t this_ts,
885 	uint32_t diff_ts,
886 	int *found,
887 	int *retval,
888 	int *false_radar_found)
889 {
890 
891 	uint32_t tabledepth = 0;
892 	struct dfs_filtertype *ft;
893 	uint64_t deltaT;
894 
895 	dfs_debug(dfs, WLAN_DEBUG_DFS1,
896 			"  *** chan freq (%d): ts %llu dur %u rssi %u",
897 			(*rs)->rs_chan.dfs_ch_freq, (uint64_t)this_ts,
898 			(*re).re_dur, (*re).re_rssi);
899 
900 	while ((tabledepth < DFS_MAX_RADAR_OVERLAP) &&
901 			((dfs->dfs_ftindextable[(*re).re_dur])[tabledepth] !=
902 			 -1) && (!*retval) && !(*false_radar_found)) {
903 		ft = dfs->dfs_radarf[((dfs->dfs_ftindextable[(*re).re_dur])
904 				[tabledepth])];
905 		dfs_debug(dfs, WLAN_DEBUG_DFS2,
906 				"  ** RD (%d): ts %x dur %u rssi %u",
907 				(*rs)->rs_chan.dfs_ch_freq, (*re).re_ts,
908 				(*re).re_dur, (*re).re_rssi);
909 
910 		if ((*re).re_rssi < ft->ft_rssithresh &&
911 				(*re).re_dur > MAX_DUR_FOR_LOW_RSSI) {
912 			dfs_debug(dfs, WLAN_DEBUG_DFS2,
913 					"Rejecting on rssi rssi=%u thresh=%u",
914 					 (*re).re_rssi,
915 					ft->ft_rssithresh);
916 			tabledepth++;
917 			continue;
918 		}
919 		deltaT = this_ts - ft->ft_last_ts;
920 		dfs_debug(dfs, WLAN_DEBUG_DFS2,
921 				"deltaT = %lld (ts: 0x%llx) (last ts: 0x%llx)",
922 				(uint64_t)deltaT, (uint64_t)this_ts,
923 				(uint64_t)ft->ft_last_ts);
924 
925 		if ((deltaT < ft->ft_minpri) && (deltaT != 0)) {
926 			/*
927 			 * This check is for the whole filter type.
928 			 * Individual filters will check this again.
929 			 * This is first line of filtering.
930 			 */
931 			dfs_debug(dfs, WLAN_DEBUG_DFS2,
932 					"Rejecting on pri pri=%lld minpri=%u",
933 					 (uint64_t)deltaT, ft->ft_minpri);
934 			tabledepth++;
935 			continue;
936 		}
937 
938 		__dfs_process_radarevent(dfs, ft, re, this_ts, found,
939 				false_radar_found);
940 
941 		ft->ft_last_ts = this_ts;
942 		*retval |= *found;
943 		tabledepth++;
944 	}
945 }
946 
947 /**
948  * dfs_check_each_b5radar() - Check each bin5 radar
949  * @dfs: Pointer to wlan_dfs structure.
950  * @re:  Pointer to re(radar event).
951  * @br: Pointer to dfs_bin5radars structure.
952  * @this_ts: Current time stamp 64bit.
953  * @diff_ts: Difference between 2 timestamps 32bit.
954  * @found: Pointer to found. If radar found or not.
955  */
956 static inline void dfs_check_each_b5radar(
957 		struct wlan_dfs *dfs,
958 		struct dfs_event *re,
959 		struct dfs_bin5radars *br,
960 		uint64_t this_ts,
961 		uint32_t diff_ts,
962 		int *found)
963 {
964 	if (dfs_bin5_check_pulse(dfs, re, br)) {
965 		/*
966 		 * This is a valid Bin5 pulse, check if it belongs to a
967 		 * burst.
968 		 */
969 		(*re).re_dur = dfs_retain_bin5_burst_pattern(dfs, diff_ts,
970 				(*re).re_dur);
971 		/*
972 		 * Remember our computed duration for the next pulse in the
973 		 * burst (if needed).
974 		 */
975 		dfs->dfs_rinfo.dfs_bin5_chirp_ts = this_ts;
976 		dfs->dfs_rinfo.dfs_last_bin5_dur = (*re).re_dur;
977 
978 		if (dfs_bin5_addpulse(dfs, br, re, this_ts))
979 			*found |= dfs_bin5_check(dfs);
980 	} else {
981 		dfs_debug(dfs, WLAN_DEBUG_DFS_BIN5_PULSE,
982 				"not a BIN5 pulse (dur=%d)", (*re).re_dur);
983 	}
984 }
985 
986 /**
987  * dfs_check_if_bin5() - Check if bin5 radar is found
988  * @dfs: Pointer to wlan_dfs structure.
989  * @re:  Pointer to re(radar event).
990  * @this_ts: Current time stamp 64bit.
991  * @diff_ts: Difference between 2 timestamps 32bit.
992  * @found: Pointer to found. If radar found or not.
993  */
994 static inline void dfs_check_if_bin5(
995 	struct wlan_dfs *dfs,
996 	struct dfs_event *re,
997 	uint64_t this_ts,
998 	uint32_t diff_ts,
999 	int *found)
1000 {
1001 	int p;
1002 
1003 	/* BIN5 pulses are FCC and Japan specific. */
1004 	if ((dfs->dfsdomain == DFS_FCC_DOMAIN) ||
1005 	    (dfs->dfsdomain == DFS_MKK4_DOMAIN) ||
1006 	    (dfs->dfsdomain == DFS_MKKN_DOMAIN)) {
1007 		for (p = 0; (p < dfs->dfs_rinfo.rn_numbin5radars) && (!*found);
1008 				p++) {
1009 			struct dfs_bin5radars *br;
1010 
1011 			br = &(dfs->dfs_b5radars[p]);
1012 			dfs_check_each_b5radar(dfs, re, br, this_ts, diff_ts,
1013 					found);
1014 		}
1015 	}
1016 
1017 	if (*found)
1018 		dfs_debug(dfs, WLAN_DEBUG_DFS, "Found bin5 radar");
1019 }
1020 
1021 /**
1022  * dfs_skip_the_event() - Skip the Radar event
1023  * @dfs: Pointer to wlan_dfs structure.
1024  * @re: Pointer to re(radar event).
1025  * @rs: Pointer to dfs_state.
1026  */
1027 static inline bool dfs_skip_the_event(
1028 	struct wlan_dfs *dfs,
1029 	struct dfs_event *re,
1030 	struct dfs_state **rs)
1031 {
1032 	if ((*re).re_chanindex < DFS_NUM_RADAR_STATES)
1033 		(*rs) = &dfs->dfs_radar[(*re).re_chanindex];
1034 	else
1035 		return 1;
1036 
1037 	if ((*rs)->rs_chan.dfs_ch_flagext & CHANNEL_INTERFERENCE)
1038 		return 1;
1039 
1040 	return 0;
1041 }
1042 
1043 /**
1044  * dfs_check_ts_wrap() - dfs check for timestamp wrap.
1045  * @dfs: Pointer to wlan_dfs structure.
1046  * @re: Pointer to re(radar event).
1047  * @deltafull_ts: Deltafull ts.
1048  *
1049  * Return: Deltafull ts.
1050  */
1051 static inline uint64_t dfs_check_ts_wrap(
1052 		struct wlan_dfs *dfs,
1053 		struct dfs_event *re,
1054 		uint64_t deltafull_ts)
1055 {
1056 	if (deltafull_ts >
1057 			((uint64_t)((DFS_TSMASK -
1058 					dfs->dfs_rinfo.rn_last_ts) +
1059 				1 + (*re).re_ts)))
1060 		deltafull_ts -=
1061 			(DFS_TSMASK - dfs->dfs_rinfo.rn_last_ts) +
1062 			1 + (*re).re_ts;
1063 
1064 	return deltafull_ts;
1065 }
1066 
1067 /**
1068  * dfs_calculate_ts_prefix() - Calculate deltafull ts value.
1069  * @dfs: Pointer to wlan_dfs structure.
1070  * @re: Pointer to re(radar event).
1071  */
1072 static inline void dfs_calculate_ts_prefix(
1073 		struct wlan_dfs *dfs,
1074 		struct dfs_event *re)
1075 {
1076 	uint64_t deltafull_ts;
1077 
1078 	if ((*re).re_ts <= dfs->dfs_rinfo.rn_last_ts) {
1079 		dfs->dfs_rinfo.rn_ts_prefix += (((uint64_t) 1) << DFS_TSSHIFT);
1080 		/* Now, see if it's been more than 1 wrap */
1081 		deltafull_ts = (*re).re_full_ts - dfs->dfs_rinfo.rn_lastfull_ts;
1082 		deltafull_ts = dfs_check_ts_wrap(dfs, re, deltafull_ts);
1083 		deltafull_ts >>= DFS_TSSHIFT;
1084 
1085 		if (deltafull_ts > 1)
1086 			dfs->dfs_rinfo.rn_ts_prefix +=
1087 				((deltafull_ts - 1) << DFS_TSSHIFT);
1088 	} else {
1089 		deltafull_ts = (*re).re_full_ts -
1090 			dfs->dfs_rinfo.rn_lastfull_ts;
1091 		if (deltafull_ts > (uint64_t) DFS_TSMASK) {
1092 			deltafull_ts >>= DFS_TSSHIFT;
1093 			dfs->dfs_rinfo.rn_ts_prefix +=
1094 				((deltafull_ts - 1) << DFS_TSSHIFT);
1095 		}
1096 	}
1097 }
1098 
1099 /**
1100  * dfs_calculate_timestamps() - Calculate various timestamps
1101  * @dfs: Pointer to wlan_dfs structure.
1102  * @re: Pointer to re(radar event)
1103  * @this_ts : Pointer to  this_ts (this timestamp)
1104  */
1105 
1106 static inline void  dfs_calculate_timestamps(
1107 	struct wlan_dfs *dfs,
1108 	struct dfs_event *re,
1109 	uint64_t *this_ts)
1110 {
1111 	if (dfs->dfs_rinfo.rn_lastfull_ts == 0) {
1112 		/*
1113 		 * Either not started, or 64-bit rollover exactly to
1114 		 * zero Just prepend zeros to the 15-bit ts.
1115 		 */
1116 		dfs->dfs_rinfo.rn_ts_prefix = 0;
1117 	} else {
1118 		/* WAR 23031- patch duplicate ts on very short pulses.
1119 		 * This pacth has two problems in linux environment.
1120 		 * 1)The time stamp created and hence PRI depends
1121 		 * entirely on the latency. If the latency is high, it
1122 		 * possibly can split two consecutive pulses in the
1123 		 * same burst so far away (the same amount of latency)
1124 		 * that make them look like they are from different
1125 		 * bursts. It is observed to happen too often. It sure
1126 		 * makes the detection fail.
1127 		 * 2)Even if the latency is not that bad, it simply
1128 		 * shifts the duplicate timestamps to a new duplicate
1129 		 * timestamp based on how they are processed.
1130 		 * This is not worse but not good either.
1131 		 * Take this pulse as a good one and create a probable
1132 		 * PRI later.
1133 		 */
1134 		if ((*re).re_dur == 0 && (*re).re_ts ==
1135 				dfs->dfs_rinfo.rn_last_unique_ts) {
1136 			debug_dup[debug_dup_cnt++] = '1';
1137 			dfs_debug(dfs, WLAN_DEBUG_DFS1, "deltaT is 0");
1138 		} else {
1139 			dfs->dfs_rinfo.rn_last_unique_ts = (*re).re_ts;
1140 			debug_dup[debug_dup_cnt++] = '0';
1141 		}
1142 
1143 		if (debug_dup_cnt >= 32)
1144 			debug_dup_cnt = 0;
1145 
1146 		dfs_calculate_ts_prefix(dfs, re);
1147 	}
1148 
1149 	/*
1150 	 * At this stage rn_ts_prefix has either been blanked or
1151 	 * calculated, so it's safe to use.
1152 	 */
1153 	*this_ts = dfs->dfs_rinfo.rn_ts_prefix | ((uint64_t) (*re).re_ts);
1154 	dfs->dfs_rinfo.rn_lastfull_ts = (*re).re_full_ts;
1155 	dfs->dfs_rinfo.rn_last_ts = (*re).re_ts;
1156 }
1157 
1158 /**
1159  * dfs_add_to_pulseline - Extract necessary items from dfs_event and
1160  * add it as pulse in the pulseline
1161  * @dfs: Pointer to wlan_dfs structure.
1162  * @re:  Pointer to re(radar event)
1163  * @this_ts: Pointer to  this_ts (this timestamp)
1164  * @diff_ts: Diff ts.
1165  * @index: Pointer to get index value.
1166  */
1167 static inline void dfs_add_to_pulseline(
1168 	struct wlan_dfs *dfs,
1169 	struct dfs_event *re,
1170 	uint64_t *this_ts,
1171 	uint32_t *test_ts,
1172 	uint32_t *diff_ts,
1173 	uint32_t *index)
1174 {
1175 	struct dfs_pulseline *pl;
1176 
1177 	/*
1178 	 * Calculate the start of the radar pulse.
1179 	 *
1180 	 * The TSF is stamped by the MAC upon reception of the event,
1181 	 * which is (typically?) at the end of the event. But the
1182 	 * pattern matching code expects the event timestamps to be at
1183 	 * the start of the event. So to fake it, we subtract the pulse
1184 	 * duration from the given TSF. This is done after the 64-bit
1185 	 * timestamp has been calculated so long pulses correctly
1186 	 * under-wrap the counter.  Ie, if this was done on the 32
1187 	 * (or 15!) bit TSF when the TSF value is closed to 0, it will
1188 	 * underflow to 0xfffffXX, which would mess up the logical "OR"
1189 	 * operation done above.
1190 	 * This isn't valid for Peregrine as the hardware gives us the
1191 	 * actual TSF offset of the radar event, not just the MAC TSF
1192 	 * of the completed receive.
1193 	 *
1194 	 * XXX TODO: ensure that the TLV PHY error processing code will
1195 	 * correctly calculate the TSF to be the start of the radar
1196 	 * pulse.
1197 	 *
1198 	 * XXX TODO TODO: modify the TLV parsing code to subtract the
1199 	 * duration from the TSF, based on the current fast clock value.
1200 	 */
1201 	if ((!dfs->dfs_caps.wlan_chip_is_bb_tlv) && (*re).re_dur != 1)
1202 		*this_ts -= (*re).re_dur;
1203 
1204 	pl = dfs->pulses;
1205 	/* Save the pulse parameters in the pulse buffer(pulse line). */
1206 	*index = (pl->pl_lastelem + 1) & DFS_MAX_PULSE_BUFFER_MASK;
1207 
1208 	if (pl->pl_numelems == DFS_MAX_PULSE_BUFFER_SIZE)
1209 		pl->pl_firstelem = (pl->pl_firstelem+1) &
1210 			DFS_MAX_PULSE_BUFFER_MASK;
1211 	else
1212 		pl->pl_numelems++;
1213 
1214 	pl->pl_lastelem = *index;
1215 	pl->pl_elems[*index].p_time = *this_ts;
1216 	pl->pl_elems[*index].p_dur = (*re).re_dur;
1217 	pl->pl_elems[*index].p_rssi = (*re).re_rssi;
1218 	pl->pl_elems[*index].p_sidx = (*re).re_sidx;
1219 	pl->pl_elems[*index].p_delta_peak = (*re).re_delta_peak;
1220 	pl->pl_elems[*index].p_psidx_diff = (*re).re_psidx_diff;
1221 	*diff_ts = (uint32_t)*this_ts - *test_ts;
1222 	*test_ts = (uint32_t)*this_ts;
1223 
1224 	dfs_debug(dfs, WLAN_DEBUG_DFS1,
1225 			"ts%u %u %u diff %u pl->pl_lastelem.p_time=%llu",
1226 			(uint32_t)*this_ts, (*re).re_dur,
1227 			(*re).re_rssi, *diff_ts,
1228 			(uint64_t)pl->pl_elems[*index].p_time);
1229 }
1230 
1231 /**
1232  * dfs_conditional_clear_delaylines - Clear delay lines to remove  the
1233  * false pulses.
1234  * @dfs: Pointer to wlan_dfs structure.
1235  * @diff_ts: diff between timerstamps.
1236  * @this_ts: this timestamp value.
1237  * @re: Pointer to dfs_event structure.
1238  */
1239 static inline void dfs_conditional_clear_delaylines(
1240 	struct wlan_dfs *dfs,
1241 	uint32_t diff_ts,
1242 	uint64_t this_ts,
1243 	struct dfs_event re)
1244 {
1245 	struct dfs_pulseline *pl = dfs->pulses;
1246 	uint32_t index;
1247 
1248 	/* If diff_ts is very small, we might be getting false pulse
1249 	 * detects due to heavy interference. We might be getting
1250 	 * spectral splatter from adjacent channel. In order to prevent
1251 	 * false alarms we clear the delay-lines. This might impact
1252 	 * positive detections under harsh environments, but helps with
1253 	 * false detects.
1254 	 */
1255 
1256 	if (diff_ts < dfs->dfs_lowest_pri_limit) {
1257 		dfs->dfs_seq_num = 0;
1258 		dfs_reset_alldelaylines(dfs);
1259 		dfs_reset_radarq(dfs);
1260 
1261 		index = (pl->pl_lastelem + 1) & DFS_MAX_PULSE_BUFFER_MASK;
1262 		if (pl->pl_numelems == DFS_MAX_PULSE_BUFFER_SIZE)
1263 			pl->pl_firstelem = (pl->pl_firstelem+1) &
1264 				DFS_MAX_PULSE_BUFFER_MASK;
1265 		else
1266 			pl->pl_numelems++;
1267 
1268 		pl->pl_lastelem = index;
1269 		pl->pl_elems[index].p_time = this_ts;
1270 		pl->pl_elems[index].p_dur = re.re_dur;
1271 		pl->pl_elems[index].p_rssi = re.re_rssi;
1272 		pl->pl_elems[index].p_sidx = re.re_sidx;
1273 		pl->pl_elems[index].p_delta_peak = re.re_delta_peak;
1274 		pl->pl_elems[index].p_psidx_diff = re.re_psidx_diff;
1275 		dfs->dfs_seq_num++;
1276 		pl->pl_elems[index].p_seq_num = dfs->dfs_seq_num;
1277 	}
1278 }
1279 
1280 /**
1281  * dfs_process_each_radarevent - remove each event from the dfs radar queue
1282  * and process it.
1283  * @dfs: Pointer to wlan_dfs structure.
1284  * @chan: Pointer to DFS current channel.
1285  * @rs: Pointer to dfs_state structure.
1286  * @seg_id: segment id.
1287  * @retval: pointer to retval.
1288  * @false_radar_found: pointer to false radar found.
1289  *
1290  * Return: If radar found then return 1 else return 0.
1291  */
1292 static inline int dfs_process_each_radarevent(
1293 	struct wlan_dfs *dfs,
1294 	struct dfs_channel *chan,
1295 	struct dfs_state **rs,
1296 	uint8_t *seg_id,
1297 	int *retval,
1298 	int *false_radar_found)
1299 {
1300 	struct dfs_event re, *event;
1301 	int found, empty;
1302 	int events_processed = 0;
1303 	uint64_t this_ts;
1304 	static uint32_t test_ts;
1305 	static uint32_t diff_ts;
1306 	uint32_t index;
1307 
1308 	dfs_is_radarq_empty(dfs, &empty);
1309 
1310 	while ((!empty) && (!*retval) && !(*false_radar_found) &&
1311 			(events_processed < MAX_EVENTS)) {
1312 		dfs_remove_event_from_radarq(dfs, &event);
1313 		if (!event) {
1314 			empty = 1;
1315 			break;
1316 		}
1317 		events_processed++;
1318 		re = *event;
1319 
1320 		dfs_return_event_to_eventq(dfs, event);
1321 
1322 		*seg_id = re.re_seg_id;
1323 		found = 0;
1324 		if (dfs_skip_the_event(dfs, &re, rs)) {
1325 			dfs_is_radarq_empty(dfs, &empty);
1326 			continue;
1327 		}
1328 
1329 		dfs_calculate_timestamps(dfs, &re, &this_ts);
1330 
1331 		re.re_dur = dfs_process_pulse_dur(dfs, re.re_dur);
1332 
1333 		dfs_add_to_pulseline(dfs, &re, &this_ts, &test_ts, &diff_ts,
1334 				&index);
1335 
1336 		dfs_dur_check(dfs, chan, &re, diff_ts);
1337 
1338 		dfs_log_event(dfs, &re, this_ts, diff_ts, index);
1339 
1340 		dfs_conditional_clear_delaylines(dfs, diff_ts, this_ts, re);
1341 
1342 		found = 0;
1343 		if (events_processed == 1) {
1344 			dfs->dfs_min_sidx = (re).re_sidx;
1345 			dfs->dfs_max_sidx = (re).re_sidx;
1346 		}
1347 
1348 		dfs_check_if_bin5(dfs, &re, this_ts, diff_ts, &found);
1349 		if (found) {
1350 			*retval |= found;
1351 			dfs->dfs_freq_offset = DFS_SIDX_TO_FREQ_OFFSET(
1352 				   (dfs->dfs_min_sidx + dfs->dfs_max_sidx) / 2);
1353 			return 1;
1354 		}
1355 
1356 		dfs_check_if_nonbin5(dfs, &re, rs, this_ts, diff_ts, &found,
1357 				retval, false_radar_found);
1358 
1359 		dfs_is_radarq_empty(dfs, &empty);
1360 	}
1361 
1362 	return 0;
1363 }
1364 
1365 /**
1366  * dfs_false_radarfound_reset_vars () - Reset dfs variables after false radar
1367  *                                      found.
1368  * @dfs: Pointer to wlan_dfs structure.
1369  */
1370 void dfs_false_radarfound_reset_vars(
1371 	struct wlan_dfs *dfs)
1372 {
1373 	dfs->dfs_seq_num = 0;
1374 	dfs_reset_radarq(dfs);
1375 	dfs_reset_alldelaylines(dfs);
1376 	dfs->dfs_phyerr_freq_min     = 0x7fffffff;
1377 	dfs->dfs_phyerr_freq_max     = 0;
1378 	dfs->dfs_phyerr_w53_counter  = 0;
1379 	dfs->dfs_event_log_count = 0;
1380 	dfs->dfs_phyerr_count = 0;
1381 	dfs->dfs_phyerr_reject_count = 0;
1382 	dfs->dfs_phyerr_queued_count = 0;
1383 }
1384 
1385 /**
1386  * dfs_process_radarevent() - For Full Offload, FW sends segment id,freq_offset
1387  * and chirp information and gets assigned when there is radar detect. In
1388  * case of radartool bangradar enhanced command and real radar for DA and PO,
1389  * we assign these information here.
1390  *
1391  * @dfs: Pointer to wlan_dfs structure.
1392  * @radar_found: Pointer to radar_found_info structure.
1393  */
1394 
1395 static void
1396 dfs_fill_radar_found_info(struct wlan_dfs *dfs,
1397 			  struct radar_found_info *radar_found)
1398 {
1399 	radar_found->segment_id = dfs->dfs_seg_id;
1400 	radar_found->freq_offset = dfs->dfs_freq_offset;
1401 	radar_found->is_chirp = dfs->dfs_is_chirp;
1402 }
1403 
1404 void dfs_radarfound_action_generic(struct wlan_dfs *dfs, uint8_t seg_id)
1405 {
1406 	struct radar_found_info *radar_found;
1407 
1408 	radar_found = qdf_mem_malloc(sizeof(*radar_found));
1409 	if (!radar_found)
1410 		return;
1411 
1412 	qdf_mem_zero(radar_found, sizeof(*radar_found));
1413 	radar_found->segment_id = seg_id;
1414 	dfs->dfs_seg_id = seg_id;
1415 	radar_found->pdev_id =
1416 		wlan_objmgr_pdev_get_pdev_id(dfs->dfs_pdev_obj);
1417 
1418 	dfs_fill_radar_found_info(dfs, radar_found);
1419 	dfs_process_radar_ind(dfs, radar_found);
1420 	qdf_mem_free(radar_found);
1421 }
1422 
1423 #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
1424 static bool dfs_is_spoof_needed(struct wlan_dfs *dfs)
1425 {
1426 	return ((utils_get_dfsdomain(dfs->dfs_pdev_obj) == DFS_FCC_DOMAIN) &&
1427 		(lmac_is_host_dfs_check_support_enabled(dfs->dfs_pdev_obj)) &&
1428 		(dfs->dfs_spoof_test_done ? dfs->dfs_use_nol : 1));
1429 }
1430 #else
1431 static inline bool dfs_is_spoof_needed(struct wlan_dfs *dfs)
1432 {
1433 	return false;
1434 }
1435 #endif
1436 
1437 /**
1438  * dfs_radar_found_action() - Radar found action
1439  * @dfs: Pointer to wlan_dfs structure.
1440  * @bangradar: true if radar is due to bangradar command.
1441  * @seg_id: Segment id.
1442  */
1443 static void dfs_radar_found_action(struct wlan_dfs *dfs,
1444 				   bool bangradar,
1445 				   uint8_t seg_id)
1446 {
1447 	/* If Host DFS confirmation is supported, save the curchan as
1448 	 * radar found chan, send radar found indication along with
1449 	 * average radar parameters to FW and start the host status
1450 	 * wait timer.
1451 	 */
1452 	if (!bangradar && dfs_is_spoof_needed(dfs)) {
1453 		dfs_radarfound_action_fcc(dfs, seg_id);
1454 	} else {
1455 		dfs_radarfound_action_generic(dfs, seg_id);
1456 	}
1457 }
1458 
1459 /**
1460  * dfs_radar_pulse_event_basic_sanity() - Check if radar pulse event is received
1461  * on a DFS channel or Zero CAC agile channel.
1462  * @dfs: Pointer to wlan_dfs structure.
1463  * @chan: Current channel.
1464  *
1465  * Return: If a radar pulse event is received on DFS channel or zero cac agile
1466  * channel return true. Otherwise, return false.
1467  */
1468 static
1469 bool dfs_radar_pulse_event_basic_sanity(struct wlan_dfs *dfs,
1470 					struct dfs_channel *chan)
1471 {
1472 	if (!chan) {
1473 		dfs_err(dfs, WLAN_DEBUG_DFS1,
1474 			"dfs->dfs_curchan is NULL");
1475 		return false;
1476 	}
1477 
1478 	if (!WLAN_IS_PRIMARY_OR_SECONDARY_CHAN_DFS(chan)) {
1479 		dfs_debug(dfs, WLAN_DEBUG_DFS1,
1480 			  "radar event on a non-DFS chan");
1481 		dfs_reset_radarq(dfs);
1482 		dfs_reset_alldelaylines(dfs);
1483 		dfs_reset_bangradar(dfs);
1484 		return false;
1485 	}
1486 	return true;
1487 }
1488 
1489 void dfs_process_radarevent(
1490 	struct wlan_dfs *dfs,
1491 	struct dfs_channel *chan)
1492 {
1493 	struct dfs_state *rs = NULL;
1494 	uint8_t   seg_id = 0;
1495 	int retval = 0;
1496 	int false_radar_found = 0;
1497 	bool bangradar = false;
1498 
1499 	if (!dfs_radar_pulse_event_basic_sanity(dfs, chan))
1500 		return;
1501 
1502 	/*
1503 	 * TEST : Simulate radar bang, make sure we add the channel to NOL
1504 	 * (bug 29968)
1505 	 */
1506 	if (dfs_handle_bangradar(dfs, chan, &rs, &seg_id, &retval)) {
1507 		if (retval)
1508 			bangradar = true;
1509 		goto dfsfound;
1510 	}
1511 
1512 	if (!dfs_handle_missing_pulses(dfs, chan))
1513 		return;
1514 
1515 	dfs_process_each_radarevent(dfs, chan, &rs, &seg_id, &retval,
1516 			&false_radar_found);
1517 
1518 dfsfound:
1519 	if (retval) {
1520 		dfs_radarfound_reset_vars(dfs, rs, chan, seg_id);
1521 		dfs_radar_found_action(dfs, bangradar, seg_id);
1522 	}
1523 
1524 	if (false_radar_found)
1525 		dfs_false_radarfound_reset_vars(dfs);
1526 }
1527