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