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