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