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