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