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