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