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