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