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