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