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