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 ori_rf_check_delta_peak = 432 rf->rf_check_delta_peak; 433 /* 434 * If FW does not send valid psidx_diff 435 * Do not do chirp check. 436 */ 437 if (rf->rf_check_delta_peak && 438 (!(re->re_flags & 439 DFS_EVENT_VALID_PSIDX_DIFF))) 440 rf->rf_check_delta_peak = false; 441 dfs_confirm_radar_check(dfs, 442 rf, ext_chan_event_flag, 443 found, 444 false_radar_found); 445 rf->rf_check_delta_peak = 446 ori_rf_check_delta_peak; 447 } 448 } 449 450 if (dfs->dfs_debug_mask & WLAN_DEBUG_DFS2) 451 if (rf->rf_patterntype != 452 WLAN_DFS_RF_PATTERN_TYPE_1) 453 dfs_print_delayline(dfs, &rf->rf_dl); 454 455 rf->rf_dl.dl_last_ts = this_ts; 456 } 457 } 458 459 if (*found) { 460 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 461 "Found on channel minDur = %d, filterId = %d", 462 ft->ft_mindur, 463 rf ? rf->rf_pulseid : -1); 464 } 465 466 return; 467 } 468 469 /** 470 * dfs_cal_average_radar_parameters() - Calculate the average radar parameters. 471 * @dfs: Pointer to wlan_dfs structure. 472 */ 473 #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST) 474 static void dfs_cal_average_radar_parameters(struct wlan_dfs *dfs) 475 { 476 int i, count = 0; 477 u_int32_t total_pri = 0; 478 u_int32_t total_duration = 0; 479 u_int32_t total_sidx = 0; 480 481 /* Calculating average PRI, Duration, SIDX from 482 * the 2nd pulse, ignoring the 1st pulse (radar_log[0]). 483 * This is because for the first pulse, the diff_ts will be 484 * (0 - current_ts) which will be a huge value. 485 * Average PRI computation will be wrong. FW returns a 486 * failure test result as PRI does not match their expected 487 * value. 488 */ 489 490 for (i = 1; (i < DFS_EVENT_LOG_SIZE) && (i < dfs->dfs_event_log_count); 491 i++) { 492 total_pri += dfs->radar_log[i].diff_ts; 493 total_duration += dfs->radar_log[i].dur; 494 total_sidx += dfs->radar_log[i].sidx; 495 count++; 496 } 497 498 if (count > 0) { 499 dfs->dfs_average_pri = total_pri / count; 500 dfs->dfs_average_duration = total_duration / count; 501 dfs->dfs_average_sidx = total_sidx / count; 502 503 dfs_info(dfs, WLAN_DEBUG_DFS2, 504 "Avg.PRI =%u, Avg.duration =%u Avg.sidx =%u", 505 dfs->dfs_average_pri, 506 dfs->dfs_average_duration, 507 dfs->dfs_average_sidx); 508 } 509 } 510 #else 511 static void dfs_cal_average_radar_parameters(struct wlan_dfs *dfs) 512 { 513 } 514 #endif 515 516 /** 517 * dfs_radarfound_reset_vars() - Reset dfs variables after radar found 518 * @dfs: Pointer to wlan_dfs structure. 519 * @rs: Pointer to dfs_state. 520 * @chan: Current channel. 521 * @seg_id: Segment id. 522 */ 523 static inline void dfs_radarfound_reset_vars( 524 struct wlan_dfs *dfs, 525 struct dfs_state *rs, 526 struct dfs_channel *chan, 527 uint8_t seg_id) 528 { 529 struct dfs_channel *thischan; 530 531 /* 532 * TODO: Instead of discarding the radar, create a workqueue 533 * if the channel change is happenning through userspace and 534 * process the radar event once the channel change is completed. 535 */ 536 537 /* Collect stats */ 538 dfs->wlan_dfs_stats.num_radar_detects++; 539 thischan = &rs->rs_chan; 540 if ((seg_id == SEG_ID_SECONDARY) && 541 (dfs_is_precac_timer_running(dfs))) 542 dfs->is_radar_during_precac = 1; 543 544 /* 545 * If event log is on then dump the radar event queue on 546 * filter match. This can be used to collect information 547 * on false radar detection. 548 */ 549 if (dfs->dfs_event_log_on) { 550 dfs_cal_average_radar_parameters(dfs); 551 dfs_print_radar_events(dfs); 552 } 553 554 dfs_reset_radarq(dfs); 555 dfs_reset_alldelaylines(dfs); 556 557 dfs_debug(dfs, WLAN_DEBUG_DFS1, 558 "Primary channel freq = %u flags=0x%x", 559 chan->dfs_ch_freq, chan->dfs_ch_flagext); 560 561 if (chan->dfs_ch_freq != thischan->dfs_ch_freq) 562 dfs_debug(dfs, WLAN_DEBUG_DFS1, 563 "Ext channel freq = %u flags=0x%x", 564 thischan->dfs_ch_freq, 565 thischan->dfs_ch_flagext); 566 567 dfs->dfs_phyerr_freq_min = 0x7fffffff; 568 dfs->dfs_phyerr_freq_max = 0; 569 dfs->dfs_phyerr_w53_counter = 0; 570 571 if (seg_id == SEG_ID_SECONDARY) { 572 dfs->wlan_dfs_stats.num_seg_two_radar_detects++; 573 dfs->is_radar_found_on_secondary_seg = 1; 574 } 575 } 576 577 /** 578 * dfs_handle_bangradar - Handle the case of bangradar 579 * @dfs: Pointer to wlan_dfs structure. 580 * @chan: Current channel. 581 * @rs: Pointer to dfs_state. 582 * Return: if bangradar then return 1. Otherwise, return 0. 583 */ 584 static inline int dfs_handle_bangradar( 585 struct wlan_dfs *dfs, 586 struct dfs_channel *chan, 587 struct dfs_state **rs, 588 uint8_t *seg_id, 589 int *retval) 590 { 591 592 if (dfs->dfs_bangradar_type) { 593 if (dfs->dfs_bangradar_type >= DFS_INVALID_BANGRADAR_TYPE) { 594 dfs_debug(dfs, WLAN_DEBUG_DFS, 595 "Invalid bangradar type"); 596 return 1; 597 } 598 /* All bangradars are processed similarly. 599 * arguments for the bangradar are already stored in 600 * respective dfs structures. 601 */ 602 603 *rs = &dfs->dfs_radar[dfs->dfs_curchan_radindex]; 604 if (dfs->dfs_seg_id == SEG_ID_SECONDARY) { 605 if (dfs_is_precac_timer_running(dfs) || 606 WLAN_IS_CHAN_11AC_VHT160(chan) || 607 WLAN_IS_CHAN_11AC_VHT80_80(chan)) { 608 dfs->is_radar_found_on_secondary_seg = 1; 609 dfs_debug(dfs, WLAN_DEBUG_DFS, 610 "bangradar on 2nd segment cfreq = %u", 611 dfs->dfs_precac_secondary_freq); 612 } else { 613 dfs_debug(dfs, WLAN_DEBUG_DFS, 614 "No second segment"); 615 return 1; 616 } 617 } 618 *seg_id = dfs->dfs_seg_id; 619 dfs_debug(dfs, WLAN_DEBUG_DFS, "bangradar %d", 620 dfs->dfs_bangradar_type); 621 *retval = 1; 622 return 1; 623 } 624 return 0; 625 } 626 627 /** 628 * dfs_process_w53_pulses() - Prrocess w53 pulses 629 * @dfs: Pointer to wlan_dfs structure. 630 * 631 * For chips that support frequency information, we can relax PRI 632 * restriction if the frequency spread is narrow. 633 */ 634 static inline void dfs_process_w53_pulses( 635 struct wlan_dfs *dfs) 636 { 637 if ((dfs->dfs_phyerr_freq_max - dfs->dfs_phyerr_freq_min) < 638 DFS_MAX_FREQ_SPREAD) 639 dfs->dfs_pri_multiplier = DFS_LARGE_PRI_MULTIPLIER; 640 641 dfs_debug(dfs, WLAN_DEBUG_DFS1, 642 "w53_counter=%d, freq_max=%d, freq_min=%d, pri_multiplier=%d", 643 dfs->dfs_phyerr_w53_counter, 644 dfs->dfs_phyerr_freq_max, dfs->dfs_phyerr_freq_min, 645 dfs->dfs_pri_multiplier); 646 647 dfs->dfs_phyerr_freq_min = 0x7fffffff; 648 dfs->dfs_phyerr_freq_max = 0; 649 } 650 651 /** 652 * dfs_handle_missing_pulses - Handle the case of missing pulses 653 * @dfs: Pointer to wlan_dfs structure. 654 * @chan: Current channel. 655 * 656 * The HW may miss some pulses especially with high channel loading. 657 * This is true for Japan W53 where channel loaoding is 50%. Also 658 * for ETSI where channel loading is 30% this can be an issue too. 659 * To take care of missing pulses, we introduce pri_margin multiplie. 660 * This is normally 2 but can be higher for W53. 661 * Return: If not enough pulses return 0. Otherwise, return 1. 662 */ 663 static inline int dfs_handle_missing_pulses( 664 struct wlan_dfs *dfs, 665 struct dfs_channel *chan) 666 { 667 if ((dfs->dfsdomain == DFS_MKK4_DOMAIN) && 668 (dfs->dfs_caps.wlan_chip_is_bb_tlv) && 669 (chan->dfs_ch_freq < FREQ_5500_MHZ)) { 670 dfs->dfs_pri_multiplier = DFS_W53_DEFAULT_PRI_MULTIPLIER; 671 /* 672 * Do not process W53 pulses unless we have a minimum number 673 * of them. 674 */ 675 if (dfs->dfs_phyerr_w53_counter >= 5) 676 dfs_process_w53_pulses(dfs); 677 else 678 return 0; 679 } 680 681 dfs_debug(dfs, WLAN_DEBUG_DFS1, "pri_multiplier=%d", 682 dfs->dfs_pri_multiplier); 683 684 return 1; 685 } 686 687 /** 688 * dfs_is_radarq_empty - check if radarq is empty 689 * @dfs: Pointer to wlan_dfs structure. 690 * @empty: Pointer to empty 691 */ 692 static inline void dfs_is_radarq_empty( 693 struct wlan_dfs *dfs, 694 int *empty) 695 { 696 WLAN_DFSQ_LOCK(dfs); 697 *empty = STAILQ_EMPTY(&(dfs->dfs_radarq)); 698 WLAN_DFSQ_UNLOCK(dfs); 699 } 700 701 /** 702 * dfs_remove_event_from_radarq - remove event from radarq 703 * @dfs: Pointer to wlan_dfs structure. 704 * @event: Double pointer to the event structure 705 */ 706 static inline void dfs_remove_event_from_radarq( 707 struct wlan_dfs *dfs, 708 struct dfs_event **event) 709 { 710 WLAN_DFSQ_LOCK(dfs); 711 *event = STAILQ_FIRST(&(dfs->dfs_radarq)); 712 if (*event) 713 STAILQ_REMOVE_HEAD(&(dfs->dfs_radarq), re_list); 714 WLAN_DFSQ_UNLOCK(dfs); 715 } 716 717 /** 718 * dfs_return_event_to_eventq - return event to eventq 719 * @dfs: Pointer to wlan_dfs structure. 720 * @event: Pointer to the event structure 721 */ 722 static inline void dfs_return_event_to_eventq( 723 struct wlan_dfs *dfs, 724 struct dfs_event *event) 725 { 726 qdf_mem_zero(event, sizeof(struct dfs_event)); 727 WLAN_DFSEVENTQ_LOCK(dfs); 728 STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), event, re_list); 729 WLAN_DFSEVENTQ_UNLOCK(dfs); 730 } 731 732 /** 733 * dfs_log_event - log dfs event 734 * @dfs: Pointer to wlan_dfs structure. 735 * @re: Pointer to dfs_event re 736 * @this_ts: Current time stamp 64bit 737 * @diff_ts: Difference between 2 timestamps 32bit 738 * @index: Index value. 739 */ 740 static inline void dfs_log_event( 741 struct wlan_dfs *dfs, 742 struct dfs_event *re, 743 uint64_t this_ts, 744 uint32_t diff_ts, 745 uint32_t index) 746 { 747 uint8_t i; 748 struct dfs_pulseline *pl = dfs->pulses; 749 750 if (dfs->dfs_event_log_on) { 751 i = dfs->dfs_event_log_count % DFS_EVENT_LOG_SIZE; 752 dfs->radar_log[i].ts = this_ts; 753 dfs->radar_log[i].diff_ts = diff_ts; 754 dfs->radar_log[i].rssi = (*re).re_rssi; 755 dfs->radar_log[i].dur = (*re).re_dur; 756 dfs->radar_log[i].seg_id = (*re).re_seg_id; 757 dfs->radar_log[i].sidx = (*re).re_sidx; 758 dfs->radar_log[i].freq_offset_khz = 759 (*re).re_freq_offset_khz; 760 dfs->radar_log[i].peak_mag = (*re).re_peak_mag; 761 dfs->radar_log[i].total_gain = (*re).re_total_gain; 762 dfs->radar_log[i].mb_gain = (*re).re_mb_gain; 763 dfs->radar_log[i].relpwr_db = (*re).re_relpwr_db; 764 dfs->radar_log[i].delta_diff = (*re).re_delta_diff; 765 dfs->radar_log[i].delta_peak = (*re).re_delta_peak; 766 dfs->radar_log[i].psidx_diff = (*re).re_psidx_diff; 767 dfs->radar_log[i].is_chirp = DFS_EVENT_NOTCHIRP(re) ? 768 0 : 1; 769 dfs->dfs_event_log_count++; 770 } 771 772 dfs->dfs_seq_num++; 773 pl->pl_elems[index].p_seq_num = dfs->dfs_seq_num; 774 } 775 776 /** 777 * dfs_check_if_nonbin5 - Check if radar, other than bin5, is found 778 * @dfs: Pointer to wlan_dfs structure. 779 * @re: Pointer to re (radar event) 780 * @rs: Double Pointer to rs (radar state) 781 * @this_ts: Current time stamp 64bit 782 * @diff_ts: Difference between 2 timestamps 32bit 783 * @found: Pointer to found. If radar found or not. 784 * @retval: Pointer to retval(return value). 785 * @false_radar_found: Pointer to false_radar_found(return value). 786 */ 787 static inline void dfs_check_if_nonbin5( 788 struct wlan_dfs *dfs, 789 struct dfs_event *re, 790 struct dfs_state **rs, 791 uint64_t this_ts, 792 uint32_t diff_ts, 793 int *found, 794 int *retval, 795 int *false_radar_found) 796 { 797 798 uint32_t tabledepth = 0; 799 struct dfs_filtertype *ft; 800 uint64_t deltaT; 801 802 dfs_debug(dfs, WLAN_DEBUG_DFS1, 803 " *** chan freq (%d): ts %llu dur %u rssi %u", 804 (*rs)->rs_chan.dfs_ch_freq, (uint64_t)this_ts, 805 (*re).re_dur, (*re).re_rssi); 806 807 while ((tabledepth < DFS_MAX_RADAR_OVERLAP) && 808 ((dfs->dfs_ftindextable[(*re).re_dur])[tabledepth] != 809 -1) && (!*retval) && !(*false_radar_found)) { 810 ft = dfs->dfs_radarf[((dfs->dfs_ftindextable[(*re).re_dur]) 811 [tabledepth])]; 812 dfs_debug(dfs, WLAN_DEBUG_DFS2, 813 " ** RD (%d): ts %x dur %u rssi %u", 814 (*rs)->rs_chan.dfs_ch_freq, (*re).re_ts, 815 (*re).re_dur, (*re).re_rssi); 816 817 if ((*re).re_rssi < ft->ft_rssithresh && 818 (*re).re_dur > MAX_DUR_FOR_LOW_RSSI) { 819 dfs_debug(dfs, WLAN_DEBUG_DFS2, 820 "Rejecting on rssi rssi=%u thresh=%u", 821 (*re).re_rssi, 822 ft->ft_rssithresh); 823 tabledepth++; 824 continue; 825 } 826 deltaT = this_ts - ft->ft_last_ts; 827 dfs_debug(dfs, WLAN_DEBUG_DFS2, 828 "deltaT = %lld (ts: 0x%llx) (last ts: 0x%llx)", 829 (uint64_t)deltaT, (uint64_t)this_ts, 830 (uint64_t)ft->ft_last_ts); 831 832 if ((deltaT < ft->ft_minpri) && (deltaT != 0)) { 833 /* 834 * This check is for the whole filter type. 835 * Individual filters will check this again. 836 * This is first line of filtering. 837 */ 838 dfs_debug(dfs, WLAN_DEBUG_DFS2, 839 "Rejecting on pri pri=%lld minpri=%u", 840 (uint64_t)deltaT, ft->ft_minpri); 841 tabledepth++; 842 continue; 843 } 844 845 __dfs_process_radarevent(dfs, ft, re, this_ts, found, 846 false_radar_found); 847 848 ft->ft_last_ts = this_ts; 849 *retval |= *found; 850 tabledepth++; 851 } 852 } 853 854 /** 855 * dfs_check_each_b5radar() - Check each bin5 radar 856 * @dfs: Pointer to wlan_dfs structure. 857 * @re: Pointer to re(radar event). 858 * @br: Pointer to dfs_bin5radars structure. 859 * @this_ts: Current time stamp 64bit. 860 * @diff_ts: Difference between 2 timestamps 32bit. 861 * @found: Pointer to found. If radar found or not. 862 */ 863 static inline void dfs_check_each_b5radar( 864 struct wlan_dfs *dfs, 865 struct dfs_event *re, 866 struct dfs_bin5radars *br, 867 uint64_t this_ts, 868 uint32_t diff_ts, 869 int *found) 870 { 871 if (dfs_bin5_check_pulse(dfs, re, br)) { 872 /* 873 * This is a valid Bin5 pulse, check if it belongs to a 874 * burst. 875 */ 876 (*re).re_dur = dfs_retain_bin5_burst_pattern(dfs, diff_ts, 877 (*re).re_dur); 878 /* 879 * Remember our computed duration for the next pulse in the 880 * burst (if needed). 881 */ 882 dfs->dfs_rinfo.dfs_bin5_chirp_ts = this_ts; 883 dfs->dfs_rinfo.dfs_last_bin5_dur = (*re).re_dur; 884 885 if (dfs_bin5_addpulse(dfs, br, re, this_ts)) 886 *found |= dfs_bin5_check(dfs); 887 } else { 888 dfs_debug(dfs, WLAN_DEBUG_DFS_BIN5_PULSE, 889 "not a BIN5 pulse (dur=%d)", (*re).re_dur); 890 } 891 } 892 893 /** 894 * dfs_check_if_bin5() - Check if bin5 radar is found 895 * @dfs: Pointer to wlan_dfs structure. 896 * @re: Pointer to re(radar event). 897 * @this_ts: Current time stamp 64bit. 898 * @diff_ts: Difference between 2 timestamps 32bit. 899 * @found: Pointer to found. If radar found or not. 900 */ 901 static inline void dfs_check_if_bin5( 902 struct wlan_dfs *dfs, 903 struct dfs_event *re, 904 uint64_t this_ts, 905 uint32_t diff_ts, 906 int *found) 907 { 908 int p; 909 910 /* BIN5 pulses are FCC and Japan specific. */ 911 if ((dfs->dfsdomain == DFS_FCC_DOMAIN) || 912 (dfs->dfsdomain == DFS_MKK4_DOMAIN)) { 913 for (p = 0; (p < dfs->dfs_rinfo.rn_numbin5radars) && (!*found); 914 p++) { 915 struct dfs_bin5radars *br; 916 917 br = &(dfs->dfs_b5radars[p]); 918 dfs_check_each_b5radar(dfs, re, br, this_ts, diff_ts, 919 found); 920 } 921 } 922 923 if (*found) 924 dfs_debug(dfs, WLAN_DEBUG_DFS, "Found bin5 radar"); 925 } 926 927 /** 928 * dfs_skip_the_event() - Skip the Radar event 929 * @dfs: Pointer to wlan_dfs structure. 930 * @re: Pointer to re(radar event). 931 * @rs: Pointer to dfs_state. 932 */ 933 static inline bool dfs_skip_the_event( 934 struct wlan_dfs *dfs, 935 struct dfs_event *re, 936 struct dfs_state **rs) 937 { 938 if ((*re).re_chanindex < DFS_NUM_RADAR_STATES) 939 (*rs) = &dfs->dfs_radar[(*re).re_chanindex]; 940 else 941 return 1; 942 943 if ((*rs)->rs_chan.dfs_ch_flagext & CHANNEL_INTERFERENCE) 944 return 1; 945 946 return 0; 947 } 948 949 /** 950 * dfs_check_ts_wrap() - dfs check for timestamp wrap. 951 * @dfs: Pointer to wlan_dfs structure. 952 * @re: Pointer to re(radar event). 953 * @deltafull_ts: Deltafull ts. 954 * 955 * Return: Deltafull ts. 956 */ 957 static inline uint64_t dfs_check_ts_wrap( 958 struct wlan_dfs *dfs, 959 struct dfs_event *re, 960 uint64_t deltafull_ts) 961 { 962 if (deltafull_ts > 963 ((uint64_t)((DFS_TSMASK - 964 dfs->dfs_rinfo.rn_last_ts) + 965 1 + (*re).re_ts))) 966 deltafull_ts -= 967 (DFS_TSMASK - dfs->dfs_rinfo.rn_last_ts) + 968 1 + (*re).re_ts; 969 970 return deltafull_ts; 971 } 972 973 /** 974 * dfs_calculate_ts_prefix() - Calculate deltafull ts value. 975 * @dfs: Pointer to wlan_dfs structure. 976 * @re: Pointer to re(radar event). 977 */ 978 static inline void dfs_calculate_ts_prefix( 979 struct wlan_dfs *dfs, 980 struct dfs_event *re) 981 { 982 uint64_t deltafull_ts; 983 984 if ((*re).re_ts <= dfs->dfs_rinfo.rn_last_ts) { 985 dfs->dfs_rinfo.rn_ts_prefix += (((uint64_t) 1) << DFS_TSSHIFT); 986 /* Now, see if it's been more than 1 wrap */ 987 deltafull_ts = (*re).re_full_ts - dfs->dfs_rinfo.rn_lastfull_ts; 988 deltafull_ts = dfs_check_ts_wrap(dfs, re, deltafull_ts); 989 deltafull_ts >>= DFS_TSSHIFT; 990 991 if (deltafull_ts > 1) 992 dfs->dfs_rinfo.rn_ts_prefix += 993 ((deltafull_ts - 1) << DFS_TSSHIFT); 994 } else { 995 deltafull_ts = (*re).re_full_ts - 996 dfs->dfs_rinfo.rn_lastfull_ts; 997 if (deltafull_ts > (uint64_t) DFS_TSMASK) { 998 deltafull_ts >>= DFS_TSSHIFT; 999 dfs->dfs_rinfo.rn_ts_prefix += 1000 ((deltafull_ts - 1) << DFS_TSSHIFT); 1001 } 1002 } 1003 } 1004 1005 /** 1006 * dfs_calculate_timestamps() - Calculate various timestamps 1007 * @dfs: Pointer to wlan_dfs structure. 1008 * @re: Pointer to re(radar event) 1009 * @this_ts : Pointer to this_ts (this timestamp) 1010 */ 1011 1012 static inline void dfs_calculate_timestamps( 1013 struct wlan_dfs *dfs, 1014 struct dfs_event *re, 1015 uint64_t *this_ts) 1016 { 1017 if (dfs->dfs_rinfo.rn_lastfull_ts == 0) { 1018 /* 1019 * Either not started, or 64-bit rollover exactly to 1020 * zero Just prepend zeros to the 15-bit ts. 1021 */ 1022 dfs->dfs_rinfo.rn_ts_prefix = 0; 1023 } else { 1024 /* WAR 23031- patch duplicate ts on very short pulses. 1025 * This pacth has two problems in linux environment. 1026 * 1)The time stamp created and hence PRI depends 1027 * entirely on the latency. If the latency is high, it 1028 * possibly can split two consecutive pulses in the 1029 * same burst so far away (the same amount of latency) 1030 * that make them look like they are from differenct 1031 * bursts. It is observed to happen too often. It sure 1032 * makes the detection fail. 1033 * 2)Even if the latency is not that bad, it simply 1034 * shifts the duplicate timestamps to a new duplicate 1035 * timestamp based on how they are processed. 1036 * This is not worse but not good either. 1037 * Take this pulse as a good one and create a probable 1038 * PRI later. 1039 */ 1040 if ((*re).re_dur == 0 && (*re).re_ts == 1041 dfs->dfs_rinfo.rn_last_unique_ts) { 1042 debug_dup[debug_dup_cnt++] = '1'; 1043 dfs_debug(dfs, WLAN_DEBUG_DFS1, "deltaT is 0"); 1044 } else { 1045 dfs->dfs_rinfo.rn_last_unique_ts = (*re).re_ts; 1046 debug_dup[debug_dup_cnt++] = '0'; 1047 } 1048 1049 if (debug_dup_cnt >= 32) 1050 debug_dup_cnt = 0; 1051 1052 dfs_calculate_ts_prefix(dfs, re); 1053 } 1054 1055 /* 1056 * At this stage rn_ts_prefix has either been blanked or 1057 * calculated, so it's safe to use. 1058 */ 1059 *this_ts = dfs->dfs_rinfo.rn_ts_prefix | ((uint64_t) (*re).re_ts); 1060 dfs->dfs_rinfo.rn_lastfull_ts = (*re).re_full_ts; 1061 dfs->dfs_rinfo.rn_last_ts = (*re).re_ts; 1062 } 1063 1064 /** 1065 * dfs_add_to_pulseline - Extract necessary items from dfs_event and 1066 * add it as pulse in the pulseline 1067 * @dfs: Pointer to wlan_dfs structure. 1068 * @re: Pointer to re(radar event) 1069 * @this_ts: Pointer to this_ts (this timestamp) 1070 * @diff_ts: Diff ts. 1071 * @index: Pointer to get index value. 1072 */ 1073 static inline void dfs_add_to_pulseline( 1074 struct wlan_dfs *dfs, 1075 struct dfs_event *re, 1076 uint64_t *this_ts, 1077 uint32_t *test_ts, 1078 uint32_t *diff_ts, 1079 uint32_t *index) 1080 { 1081 struct dfs_pulseline *pl; 1082 1083 /* 1084 * Calculate the start of the radar pulse. 1085 * 1086 * The TSF is stamped by the MAC upon reception of the event, 1087 * which is (typically?) at the end of the event. But the 1088 * pattern matching code expects the event timestamps to be at 1089 * the start of the event. So to fake it, we subtract the pulse 1090 * duration from the given TSF. This is done after the 64-bit 1091 * timestamp has been calculated so long pulses correctly 1092 * under-wrap the counter. Ie, if this was done on the 32 1093 * (or 15!) bit TSF when the TSF value is closed to 0, it will 1094 * underflow to 0xfffffXX, which would mess up the logical "OR" 1095 * operation done above. 1096 * This isn't valid for Peregrine as the hardware gives us the 1097 * actual TSF offset of the radar event, not just the MAC TSF 1098 * of the completed receive. 1099 * 1100 * XXX TODO: ensure that the TLV PHY error processing code will 1101 * correctly calculate the TSF to be the start of the radar 1102 * pulse. 1103 * 1104 * XXX TODO TODO: modify the TLV parsing code to subtract the 1105 * duration from the TSF, based on the current fast clock value. 1106 */ 1107 if ((!dfs->dfs_caps.wlan_chip_is_bb_tlv) && (*re).re_dur != 1) 1108 *this_ts -= (*re).re_dur; 1109 1110 pl = dfs->pulses; 1111 /* Save the pulse parameters in the pulse buffer(pulse line). */ 1112 *index = (pl->pl_lastelem + 1) & DFS_MAX_PULSE_BUFFER_MASK; 1113 1114 if (pl->pl_numelems == DFS_MAX_PULSE_BUFFER_SIZE) 1115 pl->pl_firstelem = (pl->pl_firstelem+1) & 1116 DFS_MAX_PULSE_BUFFER_MASK; 1117 else 1118 pl->pl_numelems++; 1119 1120 pl->pl_lastelem = *index; 1121 pl->pl_elems[*index].p_time = *this_ts; 1122 pl->pl_elems[*index].p_dur = (*re).re_dur; 1123 pl->pl_elems[*index].p_rssi = (*re).re_rssi; 1124 pl->pl_elems[*index].p_sidx = (*re).re_sidx; 1125 pl->pl_elems[*index].p_delta_peak = (*re).re_delta_peak; 1126 pl->pl_elems[*index].p_psidx_diff = (*re).re_psidx_diff; 1127 *diff_ts = (uint32_t)*this_ts - *test_ts; 1128 *test_ts = (uint32_t)*this_ts; 1129 1130 dfs_debug(dfs, WLAN_DEBUG_DFS1, 1131 "ts%u %u %u diff %u pl->pl_lastelem.p_time=%llu", 1132 (uint32_t)*this_ts, (*re).re_dur, 1133 (*re).re_rssi, *diff_ts, 1134 (uint64_t)pl->pl_elems[*index].p_time); 1135 } 1136 1137 /** 1138 * dfs_conditional_clear_delaylines - Clear delay lines to remove the 1139 * false pulses. 1140 * @dfs: Pointer to wlan_dfs structure. 1141 * @diff_ts: diff between timerstamps. 1142 * @this_ts: this timestamp value. 1143 * @re: Pointer to dfs_event structure. 1144 */ 1145 static inline void dfs_conditional_clear_delaylines( 1146 struct wlan_dfs *dfs, 1147 uint32_t diff_ts, 1148 uint64_t this_ts, 1149 struct dfs_event re) 1150 { 1151 struct dfs_pulseline *pl = dfs->pulses; 1152 uint32_t index; 1153 1154 /* If diff_ts is very small, we might be getting false pulse 1155 * detects due to heavy interference. We might be getting 1156 * spectral splatter from adjacent channel. In order to prevent 1157 * false alarms we clear the delay-lines. This might impact 1158 * positive detections under harsh environments, but helps with 1159 * false detects. 1160 */ 1161 1162 if (diff_ts < DFS_INVALID_PRI_LIMIT) { 1163 dfs->dfs_seq_num = 0; 1164 dfs_reset_alldelaylines(dfs); 1165 dfs_reset_radarq(dfs); 1166 1167 index = (pl->pl_lastelem + 1) & DFS_MAX_PULSE_BUFFER_MASK; 1168 if (pl->pl_numelems == DFS_MAX_PULSE_BUFFER_SIZE) 1169 pl->pl_firstelem = (pl->pl_firstelem+1) & 1170 DFS_MAX_PULSE_BUFFER_MASK; 1171 else 1172 pl->pl_numelems++; 1173 1174 pl->pl_lastelem = index; 1175 pl->pl_elems[index].p_time = this_ts; 1176 pl->pl_elems[index].p_dur = re.re_dur; 1177 pl->pl_elems[index].p_rssi = re.re_rssi; 1178 pl->pl_elems[index].p_sidx = re.re_sidx; 1179 pl->pl_elems[index].p_delta_peak = re.re_delta_peak; 1180 pl->pl_elems[index].p_psidx_diff = re.re_psidx_diff; 1181 dfs->dfs_seq_num++; 1182 pl->pl_elems[index].p_seq_num = dfs->dfs_seq_num; 1183 } 1184 } 1185 1186 /** 1187 * dfs_process_each_radarevent - remove each event from the dfs radar queue 1188 * and process it. 1189 * @dfs: Pointer to wlan_dfs structure. 1190 * @chan: Pointer to DFS current channel. 1191 * @rs: Pointer to dfs_state structure. 1192 * @seg_id: segment id. 1193 * @retval: pointer to retval. 1194 * @false_radar_found: pointer to false radar found. 1195 * 1196 * Return: If radar found then return 1 else return 0. 1197 */ 1198 static inline int dfs_process_each_radarevent( 1199 struct wlan_dfs *dfs, 1200 struct dfs_channel *chan, 1201 struct dfs_state **rs, 1202 uint8_t *seg_id, 1203 int *retval, 1204 int *false_radar_found) 1205 { 1206 struct dfs_event re, *event; 1207 int found, empty; 1208 int events_processed = 0; 1209 uint64_t this_ts; 1210 static uint32_t test_ts; 1211 static uint32_t diff_ts; 1212 uint32_t index; 1213 1214 dfs_is_radarq_empty(dfs, &empty); 1215 1216 while ((!empty) && (!*retval) && !(*false_radar_found) && 1217 (events_processed < MAX_EVENTS)) { 1218 dfs_remove_event_from_radarq(dfs, &event); 1219 if (!event) { 1220 empty = 1; 1221 break; 1222 } 1223 events_processed++; 1224 re = *event; 1225 1226 dfs_return_event_to_eventq(dfs, event); 1227 1228 *seg_id = re.re_seg_id; 1229 found = 0; 1230 if (dfs_skip_the_event(dfs, &re, rs)) { 1231 dfs_is_radarq_empty(dfs, &empty); 1232 continue; 1233 } 1234 1235 dfs_calculate_timestamps(dfs, &re, &this_ts); 1236 1237 re.re_dur = dfs_process_pulse_dur(dfs, re.re_dur); 1238 1239 dfs_add_to_pulseline(dfs, &re, &this_ts, &test_ts, &diff_ts, 1240 &index); 1241 1242 dfs_log_event(dfs, &re, this_ts, diff_ts, index); 1243 1244 dfs_conditional_clear_delaylines(dfs, diff_ts, this_ts, re); 1245 1246 found = 0; 1247 if (events_processed == 1) { 1248 dfs->dfs_min_sidx = (re).re_sidx; 1249 dfs->dfs_max_sidx = (re).re_sidx; 1250 } 1251 1252 dfs_check_if_bin5(dfs, &re, this_ts, diff_ts, &found); 1253 if (found) { 1254 *retval |= found; 1255 dfs->dfs_freq_offset = DFS_SIDX_TO_FREQ_OFFSET( 1256 (dfs->dfs_min_sidx + dfs->dfs_max_sidx) / 2); 1257 return 1; 1258 } 1259 1260 dfs_check_if_nonbin5(dfs, &re, rs, this_ts, diff_ts, &found, 1261 retval, false_radar_found); 1262 1263 dfs_is_radarq_empty(dfs, &empty); 1264 } 1265 1266 return 0; 1267 } 1268 1269 /** 1270 * dfs_false_radarfound_reset_vars () - Reset dfs variables after false radar 1271 * found. 1272 * @dfs: Pointer to wlan_dfs structure. 1273 */ 1274 void dfs_false_radarfound_reset_vars( 1275 struct wlan_dfs *dfs) 1276 { 1277 dfs->dfs_seq_num = 0; 1278 dfs_reset_radarq(dfs); 1279 dfs_reset_alldelaylines(dfs); 1280 dfs->dfs_phyerr_freq_min = 0x7fffffff; 1281 dfs->dfs_phyerr_freq_max = 0; 1282 dfs->dfs_phyerr_w53_counter = 0; 1283 dfs->dfs_event_log_count = 0; 1284 dfs->dfs_phyerr_count = 0; 1285 dfs->dfs_phyerr_reject_count = 0; 1286 dfs->dfs_phyerr_queued_count = 0; 1287 } 1288 1289 void dfs_radarfound_action_generic(struct wlan_dfs *dfs, uint8_t seg_id) 1290 { 1291 struct radar_found_info *radar_found; 1292 1293 radar_found = qdf_mem_malloc(sizeof(*radar_found)); 1294 if (!radar_found) 1295 return; 1296 1297 qdf_mem_zero(radar_found, sizeof(*radar_found)); 1298 radar_found->segment_id = seg_id; 1299 dfs->dfs_seg_id = seg_id; 1300 radar_found->pdev_id = 1301 wlan_objmgr_pdev_get_pdev_id(dfs->dfs_pdev_obj); 1302 1303 dfs_process_radar_ind(dfs, radar_found); 1304 qdf_mem_free(radar_found); 1305 } 1306 1307 void dfs_radar_found_action(struct wlan_dfs *dfs, 1308 bool bangradar, 1309 uint8_t seg_id) 1310 { 1311 /* If Host DFS confirmation is supported, save the curchan as 1312 * radar found chan, send radar found indication along with 1313 * average radar parameters to FW and start the host status 1314 * wait timer. 1315 */ 1316 if (!bangradar && 1317 (utils_get_dfsdomain(dfs->dfs_pdev_obj) == DFS_FCC_DOMAIN) && 1318 lmac_is_host_dfs_check_support_enabled(dfs->dfs_pdev_obj) && 1319 (dfs->dfs_spoof_test_done ? dfs->dfs_use_nol : 1)) { 1320 dfs_radarfound_action_fcc(dfs, seg_id); 1321 } else { 1322 dfs_radarfound_action_generic(dfs, seg_id); 1323 } 1324 } 1325 1326 void dfs_process_radarevent( 1327 struct wlan_dfs *dfs, 1328 struct dfs_channel *chan) 1329 { 1330 struct dfs_state *rs = NULL; 1331 uint8_t seg_id = 0; 1332 int retval = 0; 1333 int false_radar_found = 0; 1334 bool bangradar = false; 1335 1336 if (!dfs_radarevent_basic_sanity(dfs, chan)) 1337 return; 1338 /* 1339 * TEST : Simulate radar bang, make sure we add the channel to NOL 1340 * (bug 29968) 1341 */ 1342 if (dfs_handle_bangradar(dfs, chan, &rs, &seg_id, &retval)) { 1343 if (retval) 1344 bangradar = true; 1345 goto dfsfound; 1346 } 1347 1348 if (!dfs_handle_missing_pulses(dfs, chan)) 1349 return; 1350 1351 dfs_process_each_radarevent(dfs, chan, &rs, &seg_id, &retval, 1352 &false_radar_found); 1353 1354 dfsfound: 1355 if (retval) { 1356 dfs_radarfound_reset_vars(dfs, rs, chan, seg_id); 1357 dfs_radar_found_action(dfs, bangradar, seg_id); 1358 } 1359 1360 if (false_radar_found) 1361 dfs_false_radarfound_reset_vars(dfs); 1362 } 1363