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