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