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