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