1 /* 2 * Copyright (c) 2013, 2016-2021 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 #endif 655 656 /** 657 * dfs_handle_bangradar - Handle the case of bangradar 658 * @dfs: Pointer to wlan_dfs structure. 659 * @chan: Current channel. 660 * @rs: Pointer to dfs_state. 661 * Return: if bangradar then return 1. Otherwise, return 0. 662 */ 663 static inline int dfs_handle_bangradar( 664 struct wlan_dfs *dfs, 665 struct dfs_channel *chan, 666 struct dfs_state **rs, 667 uint8_t *seg_id, 668 int *retval) 669 { 670 671 if (dfs->dfs_bangradar_type) { 672 if (dfs->dfs_bangradar_type >= DFS_INVALID_BANGRADAR_TYPE) { 673 dfs_debug(dfs, WLAN_DEBUG_DFS, 674 "Invalid bangradar type"); 675 return 1; 676 } 677 /* All bangradars are processed similarly. 678 * arguments for the bangradar are already stored in 679 * respective dfs structures. 680 */ 681 682 *rs = &dfs->dfs_radar[dfs->dfs_curchan_radindex]; 683 if (dfs->dfs_seg_id == SEG_ID_SECONDARY) { 684 if (dfs_is_precac_timer_running(dfs) || 685 WLAN_IS_CHAN_11AC_VHT160(chan) || 686 WLAN_IS_CHAN_11AC_VHT80_80(chan)) { 687 dfs->is_radar_found_on_secondary_seg = 1; 688 dfs_print_radar_found_freq(dfs); 689 } else { 690 dfs_debug(dfs, WLAN_DEBUG_DFS, 691 "No second segment"); 692 return 1; 693 } 694 } 695 *seg_id = dfs->dfs_seg_id; 696 dfs_debug(dfs, WLAN_DEBUG_DFS, "bangradar %d", 697 dfs->dfs_bangradar_type); 698 *retval = 1; 699 return 1; 700 } 701 return 0; 702 } 703 704 /** 705 * dfs_process_w53_pulses() - Prrocess w53 pulses 706 * @dfs: Pointer to wlan_dfs structure. 707 * 708 * For chips that support frequency information, we can relax PRI 709 * restriction if the frequency spread is narrow. 710 */ 711 static inline void dfs_process_w53_pulses( 712 struct wlan_dfs *dfs) 713 { 714 if ((dfs->dfs_phyerr_freq_max - dfs->dfs_phyerr_freq_min) < 715 DFS_MAX_FREQ_SPREAD) 716 dfs->dfs_pri_multiplier = DFS_LARGE_PRI_MULTIPLIER; 717 718 dfs_debug(dfs, WLAN_DEBUG_DFS1, 719 "w53_counter=%d, freq_max=%d, freq_min=%d, pri_multiplier=%d", 720 dfs->dfs_phyerr_w53_counter, 721 dfs->dfs_phyerr_freq_max, dfs->dfs_phyerr_freq_min, 722 dfs->dfs_pri_multiplier); 723 724 dfs->dfs_phyerr_freq_min = 0x7fffffff; 725 dfs->dfs_phyerr_freq_max = 0; 726 } 727 728 /** 729 * dfs_handle_missing_pulses - Handle the case of missing pulses 730 * @dfs: Pointer to wlan_dfs structure. 731 * @chan: Current channel. 732 * 733 * The HW may miss some pulses especially with high channel loading. 734 * This is true for Japan W53 where channel loaoding is 50%. Also 735 * for ETSI where channel loading is 30% this can be an issue too. 736 * To take care of missing pulses, we introduce pri_margin multiplie. 737 * This is normally 2 but can be higher for W53. 738 * Return: If not enough pulses return 0. Otherwise, return 1. 739 */ 740 static inline int dfs_handle_missing_pulses( 741 struct wlan_dfs *dfs, 742 struct dfs_channel *chan) 743 { 744 if ((dfs->dfsdomain == DFS_MKK4_DOMAIN || 745 dfs->dfsdomain == DFS_MKKN_DOMAIN) && 746 (dfs->dfs_caps.wlan_chip_is_bb_tlv) && 747 (chan->dfs_ch_freq < FREQ_5500_MHZ)) { 748 dfs->dfs_pri_multiplier = DFS_W53_DEFAULT_PRI_MULTIPLIER; 749 /* 750 * Do not process W53 pulses unless we have a minimum number 751 * of them. 752 */ 753 if (dfs->dfs_phyerr_w53_counter >= 5) 754 dfs_process_w53_pulses(dfs); 755 else 756 return 0; 757 } 758 759 dfs_debug(dfs, WLAN_DEBUG_DFS1, "pri_multiplier=%d", 760 dfs->dfs_pri_multiplier); 761 762 return 1; 763 } 764 765 /** 766 * dfs_is_radarq_empty - check if radarq is empty 767 * @dfs: Pointer to wlan_dfs structure. 768 * @empty: Pointer to empty 769 */ 770 static inline void dfs_is_radarq_empty( 771 struct wlan_dfs *dfs, 772 int *empty) 773 { 774 WLAN_DFSQ_LOCK(dfs); 775 *empty = STAILQ_EMPTY(&(dfs->dfs_radarq)); 776 WLAN_DFSQ_UNLOCK(dfs); 777 } 778 779 /** 780 * dfs_remove_event_from_radarq - remove event from radarq 781 * @dfs: Pointer to wlan_dfs structure. 782 * @event: Double pointer to the event structure 783 */ 784 static inline void dfs_remove_event_from_radarq( 785 struct wlan_dfs *dfs, 786 struct dfs_event **event) 787 { 788 WLAN_DFSQ_LOCK(dfs); 789 *event = STAILQ_FIRST(&(dfs->dfs_radarq)); 790 if (*event) 791 STAILQ_REMOVE_HEAD(&(dfs->dfs_radarq), re_list); 792 WLAN_DFSQ_UNLOCK(dfs); 793 } 794 795 /** 796 * dfs_return_event_to_eventq - return event to eventq 797 * @dfs: Pointer to wlan_dfs structure. 798 * @event: Pointer to the event structure 799 */ 800 static inline void dfs_return_event_to_eventq( 801 struct wlan_dfs *dfs, 802 struct dfs_event *event) 803 { 804 qdf_mem_zero(event, sizeof(struct dfs_event)); 805 WLAN_DFSEVENTQ_LOCK(dfs); 806 STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), event, re_list); 807 WLAN_DFSEVENTQ_UNLOCK(dfs); 808 } 809 810 /** 811 * dfs_log_event - log dfs event 812 * @dfs: Pointer to wlan_dfs structure. 813 * @re: Pointer to dfs_event re 814 * @this_ts: Current time stamp 64bit 815 * @diff_ts: Difference between 2 timestamps 32bit 816 * @index: Index value. 817 */ 818 static inline void dfs_log_event( 819 struct wlan_dfs *dfs, 820 struct dfs_event *re, 821 uint64_t this_ts, 822 uint32_t diff_ts, 823 uint32_t index) 824 { 825 uint8_t i; 826 struct dfs_pulseline *pl = dfs->pulses; 827 828 if (dfs->dfs_event_log_on) { 829 i = dfs->dfs_event_log_count % DFS_EVENT_LOG_SIZE; 830 dfs->radar_log[i].ts = this_ts; 831 dfs->radar_log[i].diff_ts = diff_ts; 832 dfs->radar_log[i].rssi = (*re).re_rssi; 833 dfs->radar_log[i].dur = (*re).re_dur; 834 dfs->radar_log[i].seg_id = (*re).re_seg_id; 835 dfs->radar_log[i].sidx = (*re).re_sidx; 836 dfs->radar_log[i].freq_offset_khz = 837 (*re).re_freq_offset_khz; 838 dfs->radar_log[i].peak_mag = (*re).re_peak_mag; 839 dfs->radar_log[i].total_gain = (*re).re_total_gain; 840 dfs->radar_log[i].mb_gain = (*re).re_mb_gain; 841 dfs->radar_log[i].relpwr_db = (*re).re_relpwr_db; 842 dfs->radar_log[i].delta_diff = (*re).re_delta_diff; 843 dfs->radar_log[i].delta_peak = (*re).re_delta_peak; 844 dfs->radar_log[i].psidx_diff = (*re).re_psidx_diff; 845 dfs->radar_log[i].is_chirp = DFS_EVENT_NOTCHIRP(re) ? 846 0 : 1; 847 dfs->dfs_event_log_count++; 848 } 849 850 dfs->dfs_seq_num++; 851 pl->pl_elems[index].p_seq_num = dfs->dfs_seq_num; 852 } 853 854 /** 855 * dfs_check_if_nonbin5 - Check if radar, other than bin5, is found 856 * @dfs: Pointer to wlan_dfs structure. 857 * @re: Pointer to re (radar event) 858 * @rs: Double Pointer to rs (radar state) 859 * @this_ts: Current time stamp 64bit 860 * @diff_ts: Difference between 2 timestamps 32bit 861 * @found: Pointer to found. If radar found or not. 862 * @retval: Pointer to retval(return value). 863 * @false_radar_found: Pointer to false_radar_found(return value). 864 */ 865 static inline void dfs_check_if_nonbin5( 866 struct wlan_dfs *dfs, 867 struct dfs_event *re, 868 struct dfs_state **rs, 869 uint64_t this_ts, 870 uint32_t diff_ts, 871 int *found, 872 int *retval, 873 int *false_radar_found) 874 { 875 876 uint32_t tabledepth = 0; 877 struct dfs_filtertype *ft; 878 uint64_t deltaT; 879 880 dfs_debug(dfs, WLAN_DEBUG_DFS1, 881 " *** chan freq (%d): ts %llu dur %u rssi %u", 882 (*rs)->rs_chan.dfs_ch_freq, (uint64_t)this_ts, 883 (*re).re_dur, (*re).re_rssi); 884 885 while ((tabledepth < DFS_MAX_RADAR_OVERLAP) && 886 ((dfs->dfs_ftindextable[(*re).re_dur])[tabledepth] != 887 -1) && (!*retval) && !(*false_radar_found)) { 888 ft = dfs->dfs_radarf[((dfs->dfs_ftindextable[(*re).re_dur]) 889 [tabledepth])]; 890 dfs_debug(dfs, WLAN_DEBUG_DFS2, 891 " ** RD (%d): ts %x dur %u rssi %u", 892 (*rs)->rs_chan.dfs_ch_freq, (*re).re_ts, 893 (*re).re_dur, (*re).re_rssi); 894 895 if ((*re).re_rssi < ft->ft_rssithresh && 896 (*re).re_dur > MAX_DUR_FOR_LOW_RSSI) { 897 dfs_debug(dfs, WLAN_DEBUG_DFS2, 898 "Rejecting on rssi rssi=%u thresh=%u", 899 (*re).re_rssi, 900 ft->ft_rssithresh); 901 tabledepth++; 902 continue; 903 } 904 deltaT = this_ts - ft->ft_last_ts; 905 dfs_debug(dfs, WLAN_DEBUG_DFS2, 906 "deltaT = %lld (ts: 0x%llx) (last ts: 0x%llx)", 907 (uint64_t)deltaT, (uint64_t)this_ts, 908 (uint64_t)ft->ft_last_ts); 909 910 if ((deltaT < ft->ft_minpri) && (deltaT != 0)) { 911 /* 912 * This check is for the whole filter type. 913 * Individual filters will check this again. 914 * This is first line of filtering. 915 */ 916 dfs_debug(dfs, WLAN_DEBUG_DFS2, 917 "Rejecting on pri pri=%lld minpri=%u", 918 (uint64_t)deltaT, ft->ft_minpri); 919 tabledepth++; 920 continue; 921 } 922 923 __dfs_process_radarevent(dfs, ft, re, this_ts, found, 924 false_radar_found); 925 926 ft->ft_last_ts = this_ts; 927 *retval |= *found; 928 tabledepth++; 929 } 930 } 931 932 /** 933 * dfs_check_each_b5radar() - Check each bin5 radar 934 * @dfs: Pointer to wlan_dfs structure. 935 * @re: Pointer to re(radar event). 936 * @br: Pointer to dfs_bin5radars structure. 937 * @this_ts: Current time stamp 64bit. 938 * @diff_ts: Difference between 2 timestamps 32bit. 939 * @found: Pointer to found. If radar found or not. 940 */ 941 static inline void dfs_check_each_b5radar( 942 struct wlan_dfs *dfs, 943 struct dfs_event *re, 944 struct dfs_bin5radars *br, 945 uint64_t this_ts, 946 uint32_t diff_ts, 947 int *found) 948 { 949 if (dfs_bin5_check_pulse(dfs, re, br)) { 950 /* 951 * This is a valid Bin5 pulse, check if it belongs to a 952 * burst. 953 */ 954 (*re).re_dur = dfs_retain_bin5_burst_pattern(dfs, diff_ts, 955 (*re).re_dur); 956 /* 957 * Remember our computed duration for the next pulse in the 958 * burst (if needed). 959 */ 960 dfs->dfs_rinfo.dfs_bin5_chirp_ts = this_ts; 961 dfs->dfs_rinfo.dfs_last_bin5_dur = (*re).re_dur; 962 963 if (dfs_bin5_addpulse(dfs, br, re, this_ts)) 964 *found |= dfs_bin5_check(dfs); 965 } else { 966 dfs_debug(dfs, WLAN_DEBUG_DFS_BIN5_PULSE, 967 "not a BIN5 pulse (dur=%d)", (*re).re_dur); 968 } 969 } 970 971 /** 972 * dfs_check_if_bin5() - Check if bin5 radar is found 973 * @dfs: Pointer to wlan_dfs structure. 974 * @re: Pointer to re(radar event). 975 * @this_ts: Current time stamp 64bit. 976 * @diff_ts: Difference between 2 timestamps 32bit. 977 * @found: Pointer to found. If radar found or not. 978 */ 979 static inline void dfs_check_if_bin5( 980 struct wlan_dfs *dfs, 981 struct dfs_event *re, 982 uint64_t this_ts, 983 uint32_t diff_ts, 984 int *found) 985 { 986 int p; 987 988 /* BIN5 pulses are FCC and Japan specific. */ 989 if ((dfs->dfsdomain == DFS_FCC_DOMAIN) || 990 (dfs->dfsdomain == DFS_MKK4_DOMAIN) || 991 (dfs->dfsdomain == DFS_MKKN_DOMAIN)) { 992 for (p = 0; (p < dfs->dfs_rinfo.rn_numbin5radars) && (!*found); 993 p++) { 994 struct dfs_bin5radars *br; 995 996 br = &(dfs->dfs_b5radars[p]); 997 dfs_check_each_b5radar(dfs, re, br, this_ts, diff_ts, 998 found); 999 } 1000 } 1001 1002 if (*found) 1003 dfs_debug(dfs, WLAN_DEBUG_DFS, "Found bin5 radar"); 1004 } 1005 1006 /** 1007 * dfs_skip_the_event() - Skip the Radar event 1008 * @dfs: Pointer to wlan_dfs structure. 1009 * @re: Pointer to re(radar event). 1010 * @rs: Pointer to dfs_state. 1011 */ 1012 static inline bool dfs_skip_the_event( 1013 struct wlan_dfs *dfs, 1014 struct dfs_event *re, 1015 struct dfs_state **rs) 1016 { 1017 if ((*re).re_chanindex < DFS_NUM_RADAR_STATES) 1018 (*rs) = &dfs->dfs_radar[(*re).re_chanindex]; 1019 else 1020 return 1; 1021 1022 if ((*rs)->rs_chan.dfs_ch_flagext & CHANNEL_INTERFERENCE) 1023 return 1; 1024 1025 return 0; 1026 } 1027 1028 /** 1029 * dfs_check_ts_wrap() - dfs check for timestamp wrap. 1030 * @dfs: Pointer to wlan_dfs structure. 1031 * @re: Pointer to re(radar event). 1032 * @deltafull_ts: Deltafull ts. 1033 * 1034 * Return: Deltafull ts. 1035 */ 1036 static inline uint64_t dfs_check_ts_wrap( 1037 struct wlan_dfs *dfs, 1038 struct dfs_event *re, 1039 uint64_t deltafull_ts) 1040 { 1041 if (deltafull_ts > 1042 ((uint64_t)((DFS_TSMASK - 1043 dfs->dfs_rinfo.rn_last_ts) + 1044 1 + (*re).re_ts))) 1045 deltafull_ts -= 1046 (DFS_TSMASK - dfs->dfs_rinfo.rn_last_ts) + 1047 1 + (*re).re_ts; 1048 1049 return deltafull_ts; 1050 } 1051 1052 /** 1053 * dfs_calculate_ts_prefix() - Calculate deltafull ts value. 1054 * @dfs: Pointer to wlan_dfs structure. 1055 * @re: Pointer to re(radar event). 1056 */ 1057 static inline void dfs_calculate_ts_prefix( 1058 struct wlan_dfs *dfs, 1059 struct dfs_event *re) 1060 { 1061 uint64_t deltafull_ts; 1062 1063 if ((*re).re_ts <= dfs->dfs_rinfo.rn_last_ts) { 1064 dfs->dfs_rinfo.rn_ts_prefix += (((uint64_t) 1) << DFS_TSSHIFT); 1065 /* Now, see if it's been more than 1 wrap */ 1066 deltafull_ts = (*re).re_full_ts - dfs->dfs_rinfo.rn_lastfull_ts; 1067 deltafull_ts = dfs_check_ts_wrap(dfs, re, deltafull_ts); 1068 deltafull_ts >>= DFS_TSSHIFT; 1069 1070 if (deltafull_ts > 1) 1071 dfs->dfs_rinfo.rn_ts_prefix += 1072 ((deltafull_ts - 1) << DFS_TSSHIFT); 1073 } else { 1074 deltafull_ts = (*re).re_full_ts - 1075 dfs->dfs_rinfo.rn_lastfull_ts; 1076 if (deltafull_ts > (uint64_t) DFS_TSMASK) { 1077 deltafull_ts >>= DFS_TSSHIFT; 1078 dfs->dfs_rinfo.rn_ts_prefix += 1079 ((deltafull_ts - 1) << DFS_TSSHIFT); 1080 } 1081 } 1082 } 1083 1084 /** 1085 * dfs_calculate_timestamps() - Calculate various timestamps 1086 * @dfs: Pointer to wlan_dfs structure. 1087 * @re: Pointer to re(radar event) 1088 * @this_ts : Pointer to this_ts (this timestamp) 1089 */ 1090 1091 static inline void dfs_calculate_timestamps( 1092 struct wlan_dfs *dfs, 1093 struct dfs_event *re, 1094 uint64_t *this_ts) 1095 { 1096 if (dfs->dfs_rinfo.rn_lastfull_ts == 0) { 1097 /* 1098 * Either not started, or 64-bit rollover exactly to 1099 * zero Just prepend zeros to the 15-bit ts. 1100 */ 1101 dfs->dfs_rinfo.rn_ts_prefix = 0; 1102 } else { 1103 /* WAR 23031- patch duplicate ts on very short pulses. 1104 * This pacth has two problems in linux environment. 1105 * 1)The time stamp created and hence PRI depends 1106 * entirely on the latency. If the latency is high, it 1107 * possibly can split two consecutive pulses in the 1108 * same burst so far away (the same amount of latency) 1109 * that make them look like they are from differenct 1110 * bursts. It is observed to happen too often. It sure 1111 * makes the detection fail. 1112 * 2)Even if the latency is not that bad, it simply 1113 * shifts the duplicate timestamps to a new duplicate 1114 * timestamp based on how they are processed. 1115 * This is not worse but not good either. 1116 * Take this pulse as a good one and create a probable 1117 * PRI later. 1118 */ 1119 if ((*re).re_dur == 0 && (*re).re_ts == 1120 dfs->dfs_rinfo.rn_last_unique_ts) { 1121 debug_dup[debug_dup_cnt++] = '1'; 1122 dfs_debug(dfs, WLAN_DEBUG_DFS1, "deltaT is 0"); 1123 } else { 1124 dfs->dfs_rinfo.rn_last_unique_ts = (*re).re_ts; 1125 debug_dup[debug_dup_cnt++] = '0'; 1126 } 1127 1128 if (debug_dup_cnt >= 32) 1129 debug_dup_cnt = 0; 1130 1131 dfs_calculate_ts_prefix(dfs, re); 1132 } 1133 1134 /* 1135 * At this stage rn_ts_prefix has either been blanked or 1136 * calculated, so it's safe to use. 1137 */ 1138 *this_ts = dfs->dfs_rinfo.rn_ts_prefix | ((uint64_t) (*re).re_ts); 1139 dfs->dfs_rinfo.rn_lastfull_ts = (*re).re_full_ts; 1140 dfs->dfs_rinfo.rn_last_ts = (*re).re_ts; 1141 } 1142 1143 /** 1144 * dfs_add_to_pulseline - Extract necessary items from dfs_event and 1145 * add it as pulse in the pulseline 1146 * @dfs: Pointer to wlan_dfs structure. 1147 * @re: Pointer to re(radar event) 1148 * @this_ts: Pointer to this_ts (this timestamp) 1149 * @diff_ts: Diff ts. 1150 * @index: Pointer to get index value. 1151 */ 1152 static inline void dfs_add_to_pulseline( 1153 struct wlan_dfs *dfs, 1154 struct dfs_event *re, 1155 uint64_t *this_ts, 1156 uint32_t *test_ts, 1157 uint32_t *diff_ts, 1158 uint32_t *index) 1159 { 1160 struct dfs_pulseline *pl; 1161 1162 /* 1163 * Calculate the start of the radar pulse. 1164 * 1165 * The TSF is stamped by the MAC upon reception of the event, 1166 * which is (typically?) at the end of the event. But the 1167 * pattern matching code expects the event timestamps to be at 1168 * the start of the event. So to fake it, we subtract the pulse 1169 * duration from the given TSF. This is done after the 64-bit 1170 * timestamp has been calculated so long pulses correctly 1171 * under-wrap the counter. Ie, if this was done on the 32 1172 * (or 15!) bit TSF when the TSF value is closed to 0, it will 1173 * underflow to 0xfffffXX, which would mess up the logical "OR" 1174 * operation done above. 1175 * This isn't valid for Peregrine as the hardware gives us the 1176 * actual TSF offset of the radar event, not just the MAC TSF 1177 * of the completed receive. 1178 * 1179 * XXX TODO: ensure that the TLV PHY error processing code will 1180 * correctly calculate the TSF to be the start of the radar 1181 * pulse. 1182 * 1183 * XXX TODO TODO: modify the TLV parsing code to subtract the 1184 * duration from the TSF, based on the current fast clock value. 1185 */ 1186 if ((!dfs->dfs_caps.wlan_chip_is_bb_tlv) && (*re).re_dur != 1) 1187 *this_ts -= (*re).re_dur; 1188 1189 pl = dfs->pulses; 1190 /* Save the pulse parameters in the pulse buffer(pulse line). */ 1191 *index = (pl->pl_lastelem + 1) & DFS_MAX_PULSE_BUFFER_MASK; 1192 1193 if (pl->pl_numelems == DFS_MAX_PULSE_BUFFER_SIZE) 1194 pl->pl_firstelem = (pl->pl_firstelem+1) & 1195 DFS_MAX_PULSE_BUFFER_MASK; 1196 else 1197 pl->pl_numelems++; 1198 1199 pl->pl_lastelem = *index; 1200 pl->pl_elems[*index].p_time = *this_ts; 1201 pl->pl_elems[*index].p_dur = (*re).re_dur; 1202 pl->pl_elems[*index].p_rssi = (*re).re_rssi; 1203 pl->pl_elems[*index].p_sidx = (*re).re_sidx; 1204 pl->pl_elems[*index].p_delta_peak = (*re).re_delta_peak; 1205 pl->pl_elems[*index].p_psidx_diff = (*re).re_psidx_diff; 1206 *diff_ts = (uint32_t)*this_ts - *test_ts; 1207 *test_ts = (uint32_t)*this_ts; 1208 1209 dfs_debug(dfs, WLAN_DEBUG_DFS1, 1210 "ts%u %u %u diff %u pl->pl_lastelem.p_time=%llu", 1211 (uint32_t)*this_ts, (*re).re_dur, 1212 (*re).re_rssi, *diff_ts, 1213 (uint64_t)pl->pl_elems[*index].p_time); 1214 } 1215 1216 /** 1217 * dfs_conditional_clear_delaylines - Clear delay lines to remove the 1218 * false pulses. 1219 * @dfs: Pointer to wlan_dfs structure. 1220 * @diff_ts: diff between timerstamps. 1221 * @this_ts: this timestamp value. 1222 * @re: Pointer to dfs_event structure. 1223 */ 1224 static inline void dfs_conditional_clear_delaylines( 1225 struct wlan_dfs *dfs, 1226 uint32_t diff_ts, 1227 uint64_t this_ts, 1228 struct dfs_event re) 1229 { 1230 struct dfs_pulseline *pl = dfs->pulses; 1231 uint32_t index; 1232 1233 /* If diff_ts is very small, we might be getting false pulse 1234 * detects due to heavy interference. We might be getting 1235 * spectral splatter from adjacent channel. In order to prevent 1236 * false alarms we clear the delay-lines. This might impact 1237 * positive detections under harsh environments, but helps with 1238 * false detects. 1239 */ 1240 1241 if (diff_ts < dfs->dfs_lowest_pri_limit) { 1242 dfs->dfs_seq_num = 0; 1243 dfs_reset_alldelaylines(dfs); 1244 dfs_reset_radarq(dfs); 1245 1246 index = (pl->pl_lastelem + 1) & DFS_MAX_PULSE_BUFFER_MASK; 1247 if (pl->pl_numelems == DFS_MAX_PULSE_BUFFER_SIZE) 1248 pl->pl_firstelem = (pl->pl_firstelem+1) & 1249 DFS_MAX_PULSE_BUFFER_MASK; 1250 else 1251 pl->pl_numelems++; 1252 1253 pl->pl_lastelem = index; 1254 pl->pl_elems[index].p_time = this_ts; 1255 pl->pl_elems[index].p_dur = re.re_dur; 1256 pl->pl_elems[index].p_rssi = re.re_rssi; 1257 pl->pl_elems[index].p_sidx = re.re_sidx; 1258 pl->pl_elems[index].p_delta_peak = re.re_delta_peak; 1259 pl->pl_elems[index].p_psidx_diff = re.re_psidx_diff; 1260 dfs->dfs_seq_num++; 1261 pl->pl_elems[index].p_seq_num = dfs->dfs_seq_num; 1262 } 1263 } 1264 1265 /** 1266 * dfs_process_each_radarevent - remove each event from the dfs radar queue 1267 * and process it. 1268 * @dfs: Pointer to wlan_dfs structure. 1269 * @chan: Pointer to DFS current channel. 1270 * @rs: Pointer to dfs_state structure. 1271 * @seg_id: segment id. 1272 * @retval: pointer to retval. 1273 * @false_radar_found: pointer to false radar found. 1274 * 1275 * Return: If radar found then return 1 else return 0. 1276 */ 1277 static inline int dfs_process_each_radarevent( 1278 struct wlan_dfs *dfs, 1279 struct dfs_channel *chan, 1280 struct dfs_state **rs, 1281 uint8_t *seg_id, 1282 int *retval, 1283 int *false_radar_found) 1284 { 1285 struct dfs_event re, *event; 1286 int found, empty; 1287 int events_processed = 0; 1288 uint64_t this_ts; 1289 static uint32_t test_ts; 1290 static uint32_t diff_ts; 1291 uint32_t index; 1292 1293 dfs_is_radarq_empty(dfs, &empty); 1294 1295 while ((!empty) && (!*retval) && !(*false_radar_found) && 1296 (events_processed < MAX_EVENTS)) { 1297 dfs_remove_event_from_radarq(dfs, &event); 1298 if (!event) { 1299 empty = 1; 1300 break; 1301 } 1302 events_processed++; 1303 re = *event; 1304 1305 dfs_return_event_to_eventq(dfs, event); 1306 1307 *seg_id = re.re_seg_id; 1308 found = 0; 1309 if (dfs_skip_the_event(dfs, &re, rs)) { 1310 dfs_is_radarq_empty(dfs, &empty); 1311 continue; 1312 } 1313 1314 dfs_calculate_timestamps(dfs, &re, &this_ts); 1315 1316 re.re_dur = dfs_process_pulse_dur(dfs, re.re_dur); 1317 1318 dfs_add_to_pulseline(dfs, &re, &this_ts, &test_ts, &diff_ts, 1319 &index); 1320 1321 dfs_dur_check(dfs, chan, &re, diff_ts); 1322 1323 dfs_log_event(dfs, &re, this_ts, diff_ts, index); 1324 1325 dfs_conditional_clear_delaylines(dfs, diff_ts, this_ts, re); 1326 1327 found = 0; 1328 if (events_processed == 1) { 1329 dfs->dfs_min_sidx = (re).re_sidx; 1330 dfs->dfs_max_sidx = (re).re_sidx; 1331 } 1332 1333 dfs_check_if_bin5(dfs, &re, this_ts, diff_ts, &found); 1334 if (found) { 1335 *retval |= found; 1336 dfs->dfs_freq_offset = DFS_SIDX_TO_FREQ_OFFSET( 1337 (dfs->dfs_min_sidx + dfs->dfs_max_sidx) / 2); 1338 return 1; 1339 } 1340 1341 dfs_check_if_nonbin5(dfs, &re, rs, this_ts, diff_ts, &found, 1342 retval, false_radar_found); 1343 1344 dfs_is_radarq_empty(dfs, &empty); 1345 } 1346 1347 return 0; 1348 } 1349 1350 /** 1351 * dfs_false_radarfound_reset_vars () - Reset dfs variables after false radar 1352 * found. 1353 * @dfs: Pointer to wlan_dfs structure. 1354 */ 1355 void dfs_false_radarfound_reset_vars( 1356 struct wlan_dfs *dfs) 1357 { 1358 dfs->dfs_seq_num = 0; 1359 dfs_reset_radarq(dfs); 1360 dfs_reset_alldelaylines(dfs); 1361 dfs->dfs_phyerr_freq_min = 0x7fffffff; 1362 dfs->dfs_phyerr_freq_max = 0; 1363 dfs->dfs_phyerr_w53_counter = 0; 1364 dfs->dfs_event_log_count = 0; 1365 dfs->dfs_phyerr_count = 0; 1366 dfs->dfs_phyerr_reject_count = 0; 1367 dfs->dfs_phyerr_queued_count = 0; 1368 } 1369 1370 /** 1371 * dfs_process_radarevent() - For Full Offload, FW sends segment id,freq_offset 1372 * and chirp information and gets assigned when there is radar detect. In 1373 * case of radartool bangradar enhanced command and real radar for DA and PO, 1374 * we assign these information here. 1375 * 1376 * @dfs: Pointer to wlan_dfs structure. 1377 * @radar_found: Pointer to radar_found_info structure. 1378 */ 1379 1380 static void 1381 dfs_fill_radar_found_info(struct wlan_dfs *dfs, 1382 struct radar_found_info *radar_found) 1383 { 1384 radar_found->segment_id = dfs->dfs_seg_id; 1385 radar_found->freq_offset = dfs->dfs_freq_offset; 1386 radar_found->is_chirp = dfs->dfs_is_chirp; 1387 } 1388 1389 void dfs_radarfound_action_generic(struct wlan_dfs *dfs, uint8_t seg_id) 1390 { 1391 struct radar_found_info *radar_found; 1392 1393 radar_found = qdf_mem_malloc(sizeof(*radar_found)); 1394 if (!radar_found) 1395 return; 1396 1397 qdf_mem_zero(radar_found, sizeof(*radar_found)); 1398 radar_found->segment_id = seg_id; 1399 dfs->dfs_seg_id = seg_id; 1400 radar_found->pdev_id = 1401 wlan_objmgr_pdev_get_pdev_id(dfs->dfs_pdev_obj); 1402 1403 dfs_fill_radar_found_info(dfs, radar_found); 1404 dfs_process_radar_ind(dfs, radar_found); 1405 qdf_mem_free(radar_found); 1406 } 1407 1408 void dfs_radar_found_action(struct wlan_dfs *dfs, 1409 bool bangradar, 1410 uint8_t seg_id) 1411 { 1412 /* If Host DFS confirmation is supported, save the curchan as 1413 * radar found chan, send radar found indication along with 1414 * average radar parameters to FW and start the host status 1415 * wait timer. 1416 */ 1417 if (!bangradar && 1418 (utils_get_dfsdomain(dfs->dfs_pdev_obj) == DFS_FCC_DOMAIN) && 1419 lmac_is_host_dfs_check_support_enabled(dfs->dfs_pdev_obj) && 1420 (dfs->dfs_spoof_test_done ? dfs->dfs_use_nol : 1)) { 1421 dfs_radarfound_action_fcc(dfs, seg_id); 1422 } else { 1423 dfs_radarfound_action_generic(dfs, seg_id); 1424 } 1425 } 1426 1427 /** 1428 * dfs_is_radar_source_legacy_agile() - Check if radar pulse event is received 1429 * on a Zero CAC agile channel. 1430 * @dfs: Pointer to wlan_dfs structure. 1431 * 1432 * Return: If a radar pulse event is received on a zero cac agile 1433 * channel return true. Otherwise, return false. 1434 */ 1435 #if defined(ATH_SUPPORT_ZERO_CAC_DFS) 1436 static 1437 bool dfs_is_radar_source_legacy_agile(struct wlan_dfs *dfs) 1438 { 1439 if (dfs_is_legacy_precac_enabled(dfs) && 1440 dfs_is_precac_timer_running(dfs) && 1441 dfs->dfs_precac_secondary_freq_mhz) 1442 return true; 1443 return false; 1444 } 1445 #else 1446 static 1447 bool dfs_is_radar_source_legacy_agile(struct wlan_dfs *dfs) 1448 { 1449 return false; 1450 } 1451 #endif 1452 1453 /** 1454 * dfs_radar_pulse_event_basic_sanity() - Check if radar pulse event is received 1455 * on a DFS channel or Zero CAC agile channel. 1456 * @dfs: Pointer to wlan_dfs structure. 1457 * @chan: Current channel. 1458 * 1459 * Return: If a radar pulse event is received on DFS channel or zero cac agile 1460 * channel return true. Otherwise, return false. 1461 */ 1462 static 1463 bool dfs_radar_pulse_event_basic_sanity(struct wlan_dfs *dfs, 1464 struct dfs_channel *chan) 1465 { 1466 if (!chan) { 1467 dfs_err(dfs, WLAN_DEBUG_DFS1, 1468 "dfs->dfs_curchan is NULL"); 1469 return false; 1470 } 1471 1472 if (dfs_is_radar_source_legacy_agile(dfs)) 1473 return true; 1474 1475 if (!WLAN_IS_PRIMARY_OR_SECONDARY_CHAN_DFS(chan)) { 1476 dfs_debug(dfs, WLAN_DEBUG_DFS1, 1477 "radar event on a non-DFS chan"); 1478 dfs_reset_radarq(dfs); 1479 dfs_reset_alldelaylines(dfs); 1480 dfs_reset_bangradar(dfs); 1481 return false; 1482 } 1483 return true; 1484 } 1485 1486 void dfs_process_radarevent( 1487 struct wlan_dfs *dfs, 1488 struct dfs_channel *chan) 1489 { 1490 struct dfs_state *rs = NULL; 1491 uint8_t seg_id = 0; 1492 int retval = 0; 1493 int false_radar_found = 0; 1494 bool bangradar = false; 1495 1496 if (!dfs_radar_pulse_event_basic_sanity(dfs, chan)) 1497 return; 1498 1499 /* 1500 * TEST : Simulate radar bang, make sure we add the channel to NOL 1501 * (bug 29968) 1502 */ 1503 if (dfs_handle_bangradar(dfs, chan, &rs, &seg_id, &retval)) { 1504 if (retval) 1505 bangradar = true; 1506 goto dfsfound; 1507 } 1508 1509 if (!dfs_handle_missing_pulses(dfs, chan)) 1510 return; 1511 1512 dfs_process_each_radarevent(dfs, chan, &rs, &seg_id, &retval, 1513 &false_radar_found); 1514 1515 dfsfound: 1516 if (retval) { 1517 dfs_radarfound_reset_vars(dfs, rs, chan, seg_id); 1518 dfs_radar_found_action(dfs, bangradar, seg_id); 1519 } 1520 1521 if (false_radar_found) 1522 dfs_false_radarfound_reset_vars(dfs); 1523 } 1524