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