1 /* 2 * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2002-2006, 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 file contains the dfs_attach() and dfs_detach() functions as well 20 * as the dfs_control() function which is used to process ioctls related to DFS. 21 * For Linux/Mac, "radartool" is the command line tool that can be used to call 22 * various ioctls to set and get radar detection thresholds. 23 */ 24 25 #include "../dfs_zero_cac.h" 26 #include "wlan_dfs_lmac_api.h" 27 #include "wlan_dfs_mlme_api.h" 28 #include "../dfs_internal.h" 29 #include <dfs_ioctl.h> 30 31 /* 32 * Channel switch announcement (CSA) 33 * usenol=1 (default) make CSA and switch to a new channel on radar detect 34 * usenol=0, make CSA with next channel same as current on radar detect 35 * usenol=2, no CSA and stay on the same channel on radar detect 36 */ 37 38 static int usenol = 1; 39 40 /** 41 * dfs_task() - The main function to process the radar pulse. 42 * 43 * If Radar found, this marks the channel (and the extension channel, if HT40) 44 * as having seen a radar event. It marks CHAN_INTERFERENCE and will add it to 45 * the local NOL implementation. This is only done for 'usenol=1', as the other 46 * two modes don't do radar notification or CAC/CSA/NOL; it just notes there 47 * was a radar. 48 */ 49 static os_timer_func(dfs_task) 50 { 51 struct wlan_dfs *dfs = NULL; 52 53 OS_GET_TIMER_ARG(dfs, struct wlan_dfs *); 54 55 if (dfs == NULL) { 56 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, "%s: dfs is NULL\n", __func__); 57 return; 58 } 59 60 if (dfs_process_radarevent(dfs, dfs->dfs_curchan)) 61 dfs_radar_found_action(dfs); 62 63 dfs->wlan_radar_tasksched = 0; 64 } 65 66 /** 67 * dfs_testtimer_task() - Sends CSA in the current channel. 68 * 69 * When the user sets usenol to 0 and inject the RADAR, AP does not mark the 70 * channel as RADAR and does not add the channel to NOL. It sends the CSA in 71 * the current channel. 72 */ 73 static os_timer_func(dfs_testtimer_task) 74 { 75 struct wlan_dfs *dfs = NULL; 76 77 OS_GET_TIMER_ARG(dfs, struct wlan_dfs *); 78 dfs->wlan_dfstest = 0; 79 80 /* 81 * Flip the channel back to the original channel. 82 * Make sure this is done properly with a CSA. 83 */ 84 DFS_PRINTK("%s: go back to channel %d\n", __func__, 85 dfs->wlan_dfstest_ieeechan); 86 dfs_mlme_start_csa(dfs->dfs_pdev_obj, dfs->wlan_dfstest_ieeechan); 87 } 88 89 int dfs_get_debug_info(struct wlan_dfs *dfs, void *data) 90 { 91 if (data) 92 *(uint32_t *)data = dfs->dfs_proc_phyerr; 93 94 return (int)dfs->dfs_proc_phyerr; 95 } 96 97 void dfs_main_timer_init(struct wlan_dfs *dfs) 98 { 99 qdf_timer_init(NULL, 100 &(dfs->wlan_dfs_task_timer), 101 dfs_task, 102 (void *)(dfs), 103 QDF_TIMER_TYPE_WAKE_APPS); 104 105 qdf_timer_init(NULL, 106 &(dfs->wlan_dfstesttimer), 107 dfs_testtimer_task, 108 (void *)dfs, 109 QDF_TIMER_TYPE_WAKE_APPS); 110 } 111 112 int dfs_create_object(struct wlan_dfs **dfs) 113 { 114 *dfs = (struct wlan_dfs *)qdf_mem_malloc(sizeof(**dfs)); 115 if (*dfs == NULL) { 116 DFS_PRINTK("%s: wlan_dfs allocation failed\n", __func__); 117 return 1; 118 } 119 120 qdf_mem_zero(*dfs, sizeof(**dfs)); 121 122 (*dfs)->dfs_curchan = (struct dfs_ieee80211_channel *)qdf_mem_malloc( 123 sizeof(struct dfs_ieee80211_channel)); 124 125 if ((*dfs)->dfs_curchan == NULL) { 126 DFS_PRINTK("%s: dfs_curchan allocation failed\n", __func__); 127 return 1; 128 } 129 130 return 0; 131 } 132 133 int dfs_main_attach(struct wlan_dfs *dfs) 134 { 135 int i, n; 136 struct wlan_dfs_radar_tab_info radar_info; 137 bool ext_chan, combined_rssi, use_enhancement, strong_signal_diversiry; 138 bool chip_is_bb_tlv, chip_is_over_sampled, chip_is_ht160; 139 bool chip_is_false_detect; 140 uint32_t fastdiv_val; 141 142 if (dfs == NULL) { 143 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS1, 144 "%s: dfs is NULL\n", __func__); 145 return 0; 146 } 147 148 /* If ignore_dfs is set to 1 then Radar detection is disabled. */ 149 if (dfs->dfs_ignore_dfs) { 150 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS1, 151 "%s: ignoring dfs\n", __func__); 152 return 0; 153 } 154 155 /* 156 * Zero out radar_info. It's possible that the attach function 157 * won't fetch an initial regulatory configuration; you really 158 * do want to ensure that the contents indicates there aren't 159 * any filters. 160 */ 161 qdf_mem_zero(&radar_info, sizeof(radar_info)); 162 163 lmac_get_caps(dfs->dfs_pdev_obj, 164 &ext_chan, 165 &combined_rssi, 166 &use_enhancement, 167 &strong_signal_diversiry, 168 &chip_is_bb_tlv, 169 &chip_is_over_sampled, 170 &chip_is_ht160, 171 &chip_is_false_detect, 172 &fastdiv_val); 173 174 dfs->dfs_caps.wlan_dfs_ext_chan_ok = ext_chan; 175 dfs->dfs_caps.wlan_dfs_combined_rssi_ok = combined_rssi; 176 dfs->dfs_caps.wlan_dfs_use_enhancement = use_enhancement; 177 dfs->dfs_caps.wlan_strong_signal_diversiry = strong_signal_diversiry; 178 dfs->dfs_caps.wlan_chip_is_bb_tlv = chip_is_bb_tlv; 179 dfs->dfs_caps.wlan_chip_is_over_sampled = chip_is_over_sampled; 180 dfs->dfs_caps.wlan_chip_is_ht160 = chip_is_ht160; 181 dfs->dfs_caps.wlan_chip_is_false_detect = chip_is_false_detect; 182 dfs->dfs_caps.wlan_fastdiv_val = fastdiv_val; 183 184 dfs_clear_stats(dfs); 185 dfs->dfs_event_log_on = 1; 186 DFS_PRINTK("%s: event log enabled by default\n", __func__); 187 188 dfs->dfs_enable = 1; 189 190 /*Verify : Passing NULL to qdf_timer_init().*/ 191 dfs_main_timer_init(dfs); 192 193 WLAN_DFSQ_LOCK_INIT(dfs); 194 STAILQ_INIT(&dfs->dfs_radarq); 195 WLAN_ARQ_LOCK_INIT(dfs); 196 STAILQ_INIT(&dfs->dfs_arq); 197 STAILQ_INIT(&(dfs->dfs_eventq)); 198 WLAN_DFSEVENTQ_LOCK_INIT(dfs); 199 200 dfs->events = (struct dfs_event *)qdf_mem_malloc( 201 sizeof(struct dfs_event)*DFS_MAX_EVENTS); 202 if (dfs->events == NULL) { 203 qdf_mem_free(dfs); 204 DFS_PRINTK("%s: events allocation failed\n", __func__); 205 return 1; 206 } 207 for (i = 0; i < DFS_MAX_EVENTS; i++) 208 STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), &dfs->events[i], 209 re_list); 210 211 dfs->pulses = (struct dfs_pulseline *)qdf_mem_malloc( 212 sizeof(struct dfs_pulseline)); 213 if (dfs->pulses == NULL) { 214 qdf_mem_free(dfs->events); 215 dfs->events = NULL; 216 DFS_PRINTK("%s: Pulse buffer allocation failed\n", __func__); 217 return 1; 218 } 219 220 dfs->pulses->pl_lastelem = DFS_MAX_PULSE_BUFFER_MASK; 221 222 /* Allocate memory for radar filters. */ 223 for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) { 224 dfs->dfs_radarf[n] = (struct dfs_filtertype *) 225 qdf_mem_malloc(sizeof(struct dfs_filtertype)); 226 if (dfs->dfs_radarf[n] == NULL) { 227 DFS_PRINTK( 228 "%s: cannot allocate memory for radar filter types\n", 229 __func__); 230 goto bad1; 231 } 232 qdf_mem_zero(dfs->dfs_radarf[n], sizeof(struct dfs_filtertype)); 233 } 234 235 /* Allocate memory for radar table. */ 236 dfs->dfs_radartable = (int8_t **)qdf_mem_malloc(256*sizeof(int8_t *)); 237 if (dfs->dfs_radartable == NULL) { 238 DFS_PRINTK( 239 "%s: Cannot allocate memory for radar table\n", 240 __func__); 241 goto bad1; 242 } 243 for (n = 0; n < 256; n++) { 244 dfs->dfs_radartable[n] = qdf_mem_malloc( 245 DFS_MAX_RADAR_OVERLAP*sizeof(int8_t)); 246 if (dfs->dfs_radartable[n] == NULL) { 247 DFS_PRINTK( 248 "%s: cannot allocate memory for radar table entry\n", 249 __func__); 250 goto bad2; 251 } 252 } 253 254 if (usenol == 0) 255 DFS_PRINTK("%s: NOL disabled\n", __func__); 256 else if (usenol == 2) 257 DFS_PRINTK("%s: NOL disabled; no CSA\n", __func__); 258 259 dfs->dfs_rinfo.rn_use_nol = usenol; 260 261 /* Init the cached extension channel busy for false alarm reduction */ 262 dfs->dfs_rinfo.ext_chan_busy_ts = lmac_get_tsf64(dfs->dfs_pdev_obj); 263 dfs->dfs_rinfo.dfs_ext_chan_busy = 0; 264 /* Init the Bin5 chirping related data */ 265 dfs->dfs_rinfo.dfs_bin5_chirp_ts = dfs->dfs_rinfo.ext_chan_busy_ts; 266 dfs->dfs_rinfo.dfs_last_bin5_dur = MAX_BIN5_DUR; 267 dfs->dfs_b5radars = NULL; 268 269 /* 270 * If dfs_init_radar_filters() fails, we can abort here and 271 * reconfigure when the first valid channel + radar config 272 * is available. 273 */ 274 if (dfs_init_radar_filters(dfs, &radar_info)) { 275 DFS_PRINTK( 276 "%s: Radar Filter Intialization Failed\n", 277 __func__); 278 return 1; 279 } 280 281 dfs->wlan_dfs_false_rssi_thres = RSSI_POSSIBLY_FALSE; 282 dfs->wlan_dfs_peak_mag = SEARCH_FFT_REPORT_PEAK_MAG_THRSH; 283 dfs->dfs_phyerr_freq_min = 0x7fffffff; 284 dfs->dfs_phyerr_freq_max = 0; 285 dfs->dfs_phyerr_queued_count = 0; 286 dfs->dfs_phyerr_w53_counter = 0; 287 dfs->dfs_pri_multiplier = 2; 288 dfs->wlan_dfs_nol_timeout = DFS_NOL_TIMEOUT_S; 289 290 return 0; 291 292 bad2: 293 qdf_mem_free(dfs->dfs_radartable); 294 dfs->dfs_radartable = NULL; 295 bad1: 296 for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) { 297 if (dfs->dfs_radarf[n] != NULL) { 298 qdf_mem_free(dfs->dfs_radarf[n]); 299 dfs->dfs_radarf[n] = NULL; 300 } 301 } 302 if (dfs->pulses) { 303 qdf_mem_free(dfs->pulses); 304 dfs->pulses = NULL; 305 } 306 if (dfs->events) { 307 qdf_mem_free(dfs->events); 308 dfs->events = NULL; 309 } 310 311 return 1; 312 } 313 314 int dfs_attach(struct wlan_dfs *dfs) 315 { 316 int ret; 317 318 ret = dfs_main_attach(dfs); 319 if (ret) 320 return ret; 321 322 dfs_cac_attach(dfs); 323 dfs_zero_cac_attach(dfs); 324 dfs_nol_attach(dfs); 325 326 return 0; 327 } 328 329 void dfs_stop(struct wlan_dfs *dfs) 330 { 331 dfs_init_precac_list(dfs); 332 dfs_nol_timer_cleanup(dfs); 333 dfs_clear_nolhistory(dfs); 334 } 335 336 void dfs_main_timer_reset(struct wlan_dfs *dfs) 337 { 338 if (dfs->wlan_radar_tasksched) { 339 qdf_timer_stop(&dfs->wlan_dfs_task_timer); 340 dfs->wlan_radar_tasksched = 0; 341 } 342 343 if (dfs->wlan_dfstest) { 344 qdf_timer_stop(&dfs->wlan_dfstesttimer); 345 dfs->wlan_dfstest = 0; 346 } 347 } 348 349 void dfs_reset(struct wlan_dfs *dfs) 350 { 351 if (dfs == NULL) { 352 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS_NOL, 353 "%s: sc_dfs is NULL\n", __func__); 354 return; 355 } 356 357 dfs_cac_timer_reset(dfs); 358 dfs_zero_cac_reset(dfs); 359 dfs_main_timer_reset(dfs); 360 } 361 362 void dfs_main_detach(struct wlan_dfs *dfs) 363 { 364 int n, empty; 365 366 if (!dfs->dfs_enable) 367 return; 368 369 dfs->dfs_enable = 0; 370 371 if (dfs->dfs_curchan != NULL) { 372 qdf_mem_free(dfs->dfs_curchan); 373 dfs->dfs_curchan = NULL; 374 } 375 376 dfs_reset_radarq(dfs); 377 dfs_reset_alldelaylines(dfs); 378 379 if (dfs->pulses != NULL) { 380 qdf_mem_free(dfs->pulses); 381 dfs->pulses = NULL; 382 } 383 384 for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) { 385 if (dfs->dfs_radarf[n] != NULL) { 386 qdf_mem_free(dfs->dfs_radarf[n]); 387 dfs->dfs_radarf[n] = NULL; 388 } 389 } 390 391 if (dfs->dfs_radartable != NULL) { 392 for (n = 0; n < 256; n++) { 393 if (dfs->dfs_radartable[n] != NULL) { 394 qdf_mem_free(dfs->dfs_radartable[n]); 395 dfs->dfs_radartable[n] = NULL; 396 } 397 } 398 qdf_mem_free(dfs->dfs_radartable); 399 dfs->dfs_radartable = NULL; 400 dfs->wlan_dfs_isdfsregdomain = 0; 401 } 402 403 if (dfs->dfs_b5radars != NULL) { 404 qdf_mem_free(dfs->dfs_b5radars); 405 dfs->dfs_b5radars = NULL; 406 } 407 408 dfs_reset_ar(dfs); 409 410 WLAN_ARQ_LOCK(dfs); 411 empty = STAILQ_EMPTY(&(dfs->dfs_arq)); 412 WLAN_ARQ_UNLOCK(dfs); 413 if (!empty) 414 dfs_reset_arq(dfs); 415 416 if (dfs->events != NULL) { 417 qdf_mem_free(dfs->events); 418 dfs->events = NULL; 419 } 420 } 421 422 void dfs_detach(struct wlan_dfs *dfs) 423 { 424 dfs_main_detach(dfs); 425 dfs_zero_cac_detach(dfs); 426 } 427 428 void dfs_destroy_object(struct wlan_dfs *dfs) 429 { 430 qdf_mem_free(dfs->dfs_curchan); 431 qdf_mem_free(dfs); 432 } 433 434 int dfs_radar_disable(struct wlan_dfs *dfs) 435 { 436 dfs->dfs_proc_phyerr &= ~DFS_AR_EN; 437 dfs->dfs_proc_phyerr &= ~DFS_RADAR_EN; 438 439 return 0; 440 } 441 442 int dfs_second_segment_radar_disable(struct wlan_dfs *dfs) 443 { 444 dfs->dfs_proc_phyerr &= ~DFS_SECOND_SEGMENT_RADAR_EN; 445 446 return 0; 447 } 448 449 void dfs_phyerr_param_copy(struct wlan_dfs_phyerr_param *dst, 450 struct wlan_dfs_phyerr_param *src) 451 { 452 memcpy(dst, src, sizeof(*dst)); 453 } 454 455 struct dfs_state *dfs_getchanstate(struct wlan_dfs *dfs, uint8_t *index, 456 int ext_chan_flag) 457 { 458 struct dfs_state *rs = NULL; 459 struct dfs_ieee80211_channel *cmp_ch, cmp_ch1; 460 int i; 461 QDF_STATUS err; 462 463 if (dfs == NULL) { 464 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, "%s: dfs is NULL\n", __func__); 465 return NULL; 466 } 467 468 cmp_ch = &cmp_ch1; 469 if (ext_chan_flag) { 470 err = dfs_mlme_get_extchan(dfs->dfs_pdev_obj, 471 &(cmp_ch->dfs_ch_freq), 472 &(cmp_ch->dfs_ch_flags), 473 &(cmp_ch->dfs_ch_flagext), 474 &(cmp_ch->dfs_ch_ieee), 475 &(cmp_ch->dfs_ch_vhtop_ch_freq_seg1), 476 &(cmp_ch->dfs_ch_vhtop_ch_freq_seg2)); 477 478 if (err == QDF_STATUS_SUCCESS) { 479 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, 480 "Extension channel freq = %u flags=0x%x\n", 481 cmp_ch->dfs_ch_freq, 482 cmp_ch->dfs_ch_flagext); 483 } else 484 return NULL; 485 } else { 486 cmp_ch = dfs->dfs_curchan; 487 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, 488 "Primary channel freq = %u flags=0x%x\n", 489 cmp_ch->dfs_ch_freq, cmp_ch->dfs_ch_flagext); 490 } 491 492 for (i = 0; i < DFS_NUM_RADAR_STATES; i++) { 493 if ((dfs->dfs_radar[i].rs_chan.dfs_ch_freq == 494 cmp_ch->dfs_ch_freq) && 495 (dfs->dfs_radar[i].rs_chan.dfs_ch_flags == 496 cmp_ch->dfs_ch_flags) 497 ) { 498 if (index != NULL) 499 *index = (uint8_t)i; 500 return &(dfs->dfs_radar[i]); 501 } 502 } 503 /* No existing channel found, look for first free channel state entry.*/ 504 for (i = 0; i < DFS_NUM_RADAR_STATES; i++) { 505 if (dfs->dfs_radar[i].rs_chan.dfs_ch_freq == 0) { 506 rs = &(dfs->dfs_radar[i]); 507 /* Found one, set channel info and default thresholds.*/ 508 rs->rs_chan = *cmp_ch; 509 510 /* Copy the parameters from the default set. */ 511 dfs_phyerr_param_copy(&rs->rs_param, 512 &dfs->dfs_defaultparams); 513 514 if (index != NULL) 515 *index = (uint8_t)i; 516 517 return rs; 518 } 519 } 520 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, 521 "%s: No more radar states left.\n", __func__); 522 523 return NULL; 524 } 525 526 void dfs_radar_enable(struct wlan_dfs *dfs, int no_cac, uint32_t opmode) 527 { 528 int is_ext_ch; 529 int is_fastclk = 0; 530 struct dfs_ieee80211_channel *ext_ch, extchan; 531 QDF_STATUS err = QDF_STATUS_E_FAILURE; 532 533 if (dfs == NULL) { 534 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS1, 535 "%s: dfs is NULL\n", __func__); 536 return; 537 } 538 539 is_ext_ch = IEEE80211_IS_CHAN_11N_HT40(dfs->dfs_curchan); 540 lmac_dfs_disable(dfs->dfs_pdev_obj, no_cac); 541 542 /* 543 * In all modes, if the primary is DFS then we have to 544 * enable radar detection. In HT80_80, we can have 545 * primary non-DFS 80MHz with extension 80MHz DFS. 546 */ 547 if ((IEEE80211_IS_CHAN_DFS(dfs->dfs_curchan) || 548 ((IEEE80211_IS_CHAN_11AC_VHT160(dfs->dfs_curchan) || 549 IEEE80211_IS_CHAN_11AC_VHT80_80(dfs->dfs_curchan)) && 550 IEEE80211_IS_CHAN_DFS_CFREQ2(dfs->dfs_curchan))) || 551 (dfs_is_precac_timer_running(dfs))) { 552 struct dfs_state *rs_pri = NULL, *rs_ext = NULL; 553 uint8_t index_pri, index_ext; 554 555 dfs->dfs_proc_phyerr |= DFS_AR_EN; 556 dfs->dfs_proc_phyerr |= DFS_RADAR_EN; 557 dfs->dfs_proc_phyerr |= DFS_SECOND_SEGMENT_RADAR_EN; 558 559 ext_ch = &extchan; 560 if (is_ext_ch) 561 err = dfs_mlme_get_extchan(dfs->dfs_pdev_obj, 562 &(ext_ch->dfs_ch_freq), 563 &(ext_ch->dfs_ch_flags), 564 &(ext_ch->dfs_ch_flagext), 565 &(ext_ch->dfs_ch_ieee), 566 &(ext_ch->dfs_ch_vhtop_ch_freq_seg1), 567 &(ext_ch->dfs_ch_vhtop_ch_freq_seg2)); 568 569 570 dfs_reset_alldelaylines(dfs); 571 572 rs_pri = dfs_getchanstate(dfs, &index_pri, 0); 573 if (err == QDF_STATUS_SUCCESS) { 574 rs_ext = dfs_getchanstate(dfs, &index_ext, 1); 575 } 576 577 if (rs_pri != NULL && ((err == QDF_STATUS_E_FAILURE) || 578 (rs_ext != NULL))) { 579 struct wlan_dfs_phyerr_param pe; 580 581 qdf_mem_set(&pe, '\0', sizeof(pe)); 582 583 if (index_pri != dfs->dfs_curchan_radindex) 584 dfs_reset_alldelaylines(dfs); 585 586 dfs->dfs_curchan_radindex = (int16_t)index_pri; 587 588 if (rs_ext) 589 dfs->dfs_extchan_radindex = (int16_t)index_ext; 590 591 dfs_phyerr_param_copy(&pe, &rs_pri->rs_param); 592 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS3, 593 "%s: firpwr=%d, rssi=%d, height=%d, prssi=%d, inband=%d, relpwr=%d, relstep=%d, maxlen=%d\n", 594 __func__, pe.pe_firpwr, 595 pe.pe_rrssi, pe.pe_height, 596 pe.pe_prssi, pe.pe_inband, 597 pe.pe_relpwr, pe.pe_relstep, 598 pe.pe_maxlen); 599 600 lmac_dfs_enable(dfs->dfs_pdev_obj, &is_fastclk, 601 pe.pe_firpwr, 602 pe.pe_rrssi, 603 pe.pe_height, 604 pe.pe_prssi, 605 pe.pe_inband, 606 pe.pe_relpwr, 607 pe.pe_relstep, 608 pe.pe_maxlen, 609 dfs->dfsdomain); 610 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, 611 "Enabled radar detection on channel %d\n", 612 dfs->dfs_curchan->dfs_ch_freq); 613 614 dfs->dur_multiplier = is_fastclk ? 615 DFS_FAST_CLOCK_MULTIPLIER : 616 DFS_NO_FAST_CLOCK_MULTIPLIER; 617 618 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS3, 619 "%s: duration multiplier is %d\n", 620 __func__, dfs->dur_multiplier); 621 } else 622 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, 623 "%s: No more radar states left\n", 624 __func__); 625 } 626 } 627 628 int dfs_control(struct wlan_dfs *dfs, 629 u_int id, 630 void *indata, 631 uint32_t insize, 632 void *outdata, 633 uint32_t *outsize) 634 { 635 struct wlan_dfs_phyerr_param peout; 636 struct dfs_ioctl_params *dfsparams; 637 int error = 0; 638 uint32_t val = 0; 639 struct dfsreq_nolinfo *nol; 640 uint32_t *data = NULL; 641 int i; 642 643 if (dfs == NULL) { 644 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS1, "%s DFS is null\n", __func__); 645 /* 646 * Enable/Disable DFS can be done prior to attach, 647 * So handle here. 648 */ 649 switch (id) { 650 case DFS_DISABLE_DETECT: 651 dfs->dfs_ignore_dfs = 1; 652 DFS_PRINTK( 653 "%s enable detects, ignore_dfs %d\n", 654 __func__, dfs->dfs_ignore_dfs ? 1:0); 655 break; 656 case DFS_ENABLE_DETECT: 657 dfs->dfs_ignore_dfs = 0; 658 DFS_PRINTK( 659 "%s enable detects, ignore_dfs %d\n", 660 __func__, dfs->dfs_ignore_dfs ? 1:0); 661 break; 662 default: 663 error = -EINVAL; 664 break; 665 } 666 goto bad; 667 } 668 669 switch (id) { 670 case DFS_SET_THRESH: 671 if (insize < sizeof(struct dfs_ioctl_params) || !indata) { 672 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS1, 673 "%s: insize = %d, expected = %zu bytes, indata = %p\n", 674 __func__, insize, 675 sizeof(struct dfs_ioctl_params), 676 indata); 677 error = -EINVAL; 678 break; 679 } 680 dfsparams = (struct dfs_ioctl_params *)indata; 681 if (!dfs_set_thresholds(dfs, DFS_PARAM_FIRPWR, 682 dfsparams->dfs_firpwr)) 683 error = -EINVAL; 684 if (!dfs_set_thresholds(dfs, DFS_PARAM_RRSSI, 685 dfsparams->dfs_rrssi)) 686 error = -EINVAL; 687 if (!dfs_set_thresholds(dfs, DFS_PARAM_HEIGHT, 688 dfsparams->dfs_height)) 689 error = -EINVAL; 690 if (!dfs_set_thresholds(dfs, DFS_PARAM_PRSSI, 691 dfsparams->dfs_prssi)) 692 error = -EINVAL; 693 if (!dfs_set_thresholds(dfs, DFS_PARAM_INBAND, 694 dfsparams->dfs_inband)) 695 error = -EINVAL; 696 697 /* 5413 speicfic. */ 698 if (!dfs_set_thresholds(dfs, DFS_PARAM_RELPWR, 699 dfsparams->dfs_relpwr)) 700 error = -EINVAL; 701 if (!dfs_set_thresholds(dfs, DFS_PARAM_RELSTEP, 702 dfsparams->dfs_relstep)) 703 error = -EINVAL; 704 if (!dfs_set_thresholds(dfs, DFS_PARAM_MAXLEN, 705 dfsparams->dfs_maxlen)) 706 error = -EINVAL; 707 break; 708 case DFS_GET_THRESH: 709 if (!outdata || !outsize || 710 *outsize < sizeof(struct dfs_ioctl_params)) { 711 error = -EINVAL; 712 break; 713 } 714 *outsize = sizeof(struct dfs_ioctl_params); 715 dfsparams = (struct dfs_ioctl_params *) outdata; 716 717 /* Fetch the DFS thresholds using the internal representation */ 718 (void) dfs_get_thresholds(dfs, &peout); 719 720 /* Convert them to the dfs IOCTL representation. */ 721 wlan_dfs_dfsparam_to_ioctlparam(&peout, dfsparams); 722 break; 723 case DFS_RADARDETECTS: 724 if (!outdata || !outsize || *outsize < sizeof(uint32_t)) { 725 error = -EINVAL; 726 break; 727 } 728 *outsize = sizeof(uint32_t); 729 *((uint32_t *)outdata) = dfs->wlan_dfs_stats.num_radar_detects; 730 break; 731 case DFS_DISABLE_DETECT: 732 dfs->dfs_proc_phyerr &= ~DFS_RADAR_EN; 733 dfs->dfs_proc_phyerr &= ~DFS_SECOND_SEGMENT_RADAR_EN; 734 dfs->dfs_ignore_dfs = 1; 735 DFS_PRINTK("%s enable detects, ignore_dfs %d\n", __func__, 736 dfs->dfs_ignore_dfs ? 1:0); 737 break; 738 case DFS_ENABLE_DETECT: 739 dfs->dfs_proc_phyerr |= DFS_RADAR_EN; 740 dfs->dfs_proc_phyerr |= DFS_SECOND_SEGMENT_RADAR_EN; 741 dfs->dfs_ignore_dfs = 0; 742 DFS_PRINTK("%s enable detects, ignore_dfs %d\n", __func__, 743 dfs->dfs_ignore_dfs ? 1:0); 744 break; 745 case DFS_DISABLE_FFT: 746 DFS_PRINTK("%s TODO disable FFT val=0x%x\n", __func__, val); 747 break; 748 case DFS_ENABLE_FFT: 749 DFS_PRINTK("%s TODO enable FFT val=0x%x\n", __func__, val); 750 break; 751 case DFS_SET_DEBUG_LEVEL: 752 if (insize < sizeof(uint32_t) || !indata) { 753 error = -EINVAL; 754 break; 755 } 756 dfs->dfs_debug_mask = *(uint32_t *)indata; 757 DFS_PRINTK("%s debug level now = 0x%x\n", __func__, 758 dfs->dfs_debug_mask); 759 if (dfs->dfs_debug_mask & WLAN_DEBUG_DFS3) { 760 /* Enable debug Radar Event */ 761 dfs->dfs_event_log_on = 1; 762 } else { 763 dfs->dfs_event_log_on = 0; 764 } 765 break; 766 case DFS_SET_FALSE_RSSI_THRES: 767 if (insize < sizeof(uint32_t) || !indata) { 768 error = -EINVAL; 769 break; 770 } 771 dfs->wlan_dfs_false_rssi_thres = *(uint32_t *)indata; 772 DFS_PRINTK("%s false RSSI threshold now = 0x%x\n", __func__, 773 dfs->wlan_dfs_false_rssi_thres); 774 break; 775 case DFS_SET_PEAK_MAG: 776 if (insize < sizeof(uint32_t) || !indata) { 777 error = -EINVAL; 778 break; 779 } 780 dfs->wlan_dfs_peak_mag = *(uint32_t *)indata; 781 DFS_PRINTK("%s peak_mag now = 0x%x\n", __func__, 782 dfs->wlan_dfs_peak_mag); 783 break; 784 case DFS_GET_CAC_VALID_TIME: 785 if (!outdata || !outsize || *outsize < sizeof(uint32_t)) { 786 error = -EINVAL; 787 break; 788 } 789 *outsize = sizeof(uint32_t); 790 *((uint32_t *)outdata) = dfs->dfs_cac_valid_time; 791 break; 792 case DFS_SET_CAC_VALID_TIME: 793 if (insize < sizeof(uint32_t) || !indata) { 794 error = -EINVAL; 795 break; 796 } 797 dfs->dfs_cac_valid_time = *(uint32_t *)indata; 798 DFS_PRINTK("%s dfs timeout = %d\n", __func__, 799 dfs->dfs_cac_valid_time); 800 break; 801 case DFS_IGNORE_CAC: 802 if (insize < sizeof(uint32_t) || !indata) { 803 error = -EINVAL; 804 break; 805 } 806 807 if (*(uint32_t *)indata) 808 dfs->dfs_ignore_cac = 1; 809 else 810 dfs->dfs_ignore_cac = 0; 811 812 DFS_PRINTK("%s ignore cac = 0x%x\n", __func__, 813 dfs->dfs_ignore_cac); 814 break; 815 case DFS_SET_NOL_TIMEOUT: 816 if (insize < sizeof(uint32_t) || !indata) { 817 error = -EINVAL; 818 break; 819 } 820 if (*(int *)indata) 821 dfs->wlan_dfs_nol_timeout = *(int *)indata; 822 else 823 dfs->wlan_dfs_nol_timeout = DFS_NOL_TIMEOUT_S; 824 825 DFS_PRINTK("%s nol timeout = %d sec\n", __func__, 826 dfs->wlan_dfs_nol_timeout); 827 break; 828 case DFS_MUTE_TIME: 829 if (insize < sizeof(uint32_t) || !indata) { 830 error = -EINVAL; 831 break; 832 } 833 data = (uint32_t *) indata; 834 dfs->wlan_dfstesttime = *data; 835 dfs->wlan_dfstesttime *= (1000); /* convert sec into ms */ 836 break; 837 case DFS_GET_USENOL: 838 if (!outdata || !outsize || *outsize < sizeof(uint32_t)) { 839 error = -EINVAL; 840 break; 841 } 842 *outsize = sizeof(uint32_t); 843 *((uint32_t *)outdata) = dfs->dfs_rinfo.rn_use_nol; 844 845 DFS_PRINTK( 846 "%s:#Phyerr=%d, #false detect=%d, #queued=%d\n", 847 __func__, dfs->dfs_phyerr_count, 848 dfs->dfs_phyerr_reject_count, 849 dfs->dfs_phyerr_queued_count); 850 851 DFS_PRINTK( 852 "%s:dfs_phyerr_freq_min=%d, dfs_phyerr_freq_max=%d\n", 853 __func__, dfs->dfs_phyerr_freq_min, 854 dfs->dfs_phyerr_freq_max); 855 856 DFS_PRINTK( 857 "%s:Total radar events detected=%d, entries in the radar queue follows:\n", 858 __func__, dfs->dfs_event_log_count); 859 860 for (i = 0; (i < DFS_EVENT_LOG_SIZE) && 861 (i < dfs->dfs_event_log_count); i++) { 862 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, 863 "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\n", 864 dfs->radar_log[i].ts, 865 dfs->radar_log[i].diff_ts, 866 dfs->radar_log[i].rssi, 867 dfs->radar_log[i].dur, 868 dfs->radar_log[i].is_chirp, 869 dfs->radar_log[i].seg_id, 870 dfs->radar_log[i].sidx, 871 ((int)dfs->radar_log[i].freq_offset_khz/1000), 872 ((int)abs 873 (dfs->radar_log[i].freq_offset_khz)%1000), 874 dfs->radar_log[i].peak_mag, 875 dfs->radar_log[i].total_gain, 876 dfs->radar_log[i].mb_gain, 877 dfs->radar_log[i].relpwr_db); 878 } 879 dfs->dfs_event_log_count = 0; 880 dfs->dfs_phyerr_count = 0; 881 dfs->dfs_phyerr_reject_count = 0; 882 dfs->dfs_phyerr_queued_count = 0; 883 dfs->dfs_phyerr_freq_min = 0x7fffffff; 884 dfs->dfs_phyerr_freq_max = 0; 885 break; 886 case DFS_SET_USENOL: 887 if (insize < sizeof(uint32_t) || !indata) { 888 error = -EINVAL; 889 break; 890 } 891 dfs->dfs_rinfo.rn_use_nol = *(uint32_t *)indata; 892 break; 893 case DFS_GET_NOL: 894 if (!outdata || !outsize || 895 *outsize < sizeof(struct dfsreq_nolinfo)) { 896 error = -EINVAL; 897 break; 898 } 899 *outsize = sizeof(struct dfsreq_nolinfo); 900 nol = (struct dfsreq_nolinfo *)outdata; 901 dfs_get_nol(dfs, 902 (struct dfsreq_nolelem *)nol->dfs_nol, 903 &nol->dfs_ch_nchans); 904 dfs_print_nol(dfs); 905 break; 906 case DFS_SET_NOL: 907 if (insize < sizeof(struct dfsreq_nolinfo) || !indata) { 908 error = -EINVAL; 909 break; 910 } 911 nol = (struct dfsreq_nolinfo *) indata; 912 dfs_set_nol(dfs, 913 (struct dfsreq_nolelem *)nol->dfs_nol, 914 nol->dfs_ch_nchans); 915 break; 916 case DFS_SHOW_NOL: 917 dfs_print_nol(dfs); 918 break; 919 case DFS_SHOW_NOLHISTORY: 920 dfs_print_nolhistory(dfs); 921 break; 922 case DFS_BANGRADAR: 923 dfs->dfs_bangradar = 1; 924 dfs->wlan_radar_tasksched = 1; 925 qdf_timer_mod(&dfs->wlan_dfs_task_timer, 0); 926 error = 0; 927 break; 928 case DFS_SHOW_PRECAC_LISTS: 929 dfs_print_precaclists(dfs); 930 break; 931 case DFS_RESET_PRECAC_LISTS: 932 dfs_reset_precac_lists(dfs); 933 break; 934 case DFS_SECOND_SEGMENT_BANGRADAR: 935 dfs->dfs_second_segment_bangradar = 1; 936 dfs->wlan_radar_tasksched = 1; 937 qdf_timer_mod(&dfs->wlan_dfs_task_timer, 0); 938 error = 0; 939 break; 940 default: 941 error = -EINVAL; 942 } 943 944 bad: 945 return error; 946 } 947 948 int dfs_set_thresholds(struct wlan_dfs *dfs, const uint32_t threshtype, 949 const uint32_t value) 950 { 951 int16_t chanindex; 952 struct dfs_state *rs; 953 struct wlan_dfs_phyerr_param pe; 954 int is_fastclk = 0; 955 956 if (dfs == NULL) { 957 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS1, 958 "%s: dfs is NULL\n", __func__); 959 return 0; 960 } 961 962 chanindex = dfs->dfs_curchan_radindex; 963 if ((chanindex < 0) || (chanindex >= DFS_NUM_RADAR_STATES)) { 964 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS1, 965 "%s: chanindex = %d, DFS_NUM_RADAR_STATES=%d\n", 966 __func__, chanindex, DFS_NUM_RADAR_STATES); 967 return 0; 968 } 969 970 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, 971 "%s: threshtype=%d, value=%d\n", 972 __func__, threshtype, value); 973 974 wlan_dfs_phyerr_init_noval(&pe); 975 976 rs = &(dfs->dfs_radar[chanindex]); 977 switch (threshtype) { 978 case DFS_PARAM_FIRPWR: 979 rs->rs_param.pe_firpwr = (int32_t) value; 980 pe.pe_firpwr = value; 981 break; 982 case DFS_PARAM_RRSSI: 983 rs->rs_param.pe_rrssi = value; 984 pe.pe_rrssi = value; 985 break; 986 case DFS_PARAM_HEIGHT: 987 rs->rs_param.pe_height = value; 988 pe.pe_height = value; 989 break; 990 case DFS_PARAM_PRSSI: 991 rs->rs_param.pe_prssi = value; 992 pe.pe_prssi = value; 993 break; 994 case DFS_PARAM_INBAND: 995 rs->rs_param.pe_inband = value; 996 pe.pe_inband = value; 997 break; 998 /* 5413 specific */ 999 case DFS_PARAM_RELPWR: 1000 rs->rs_param.pe_relpwr = value; 1001 pe.pe_relpwr = value; 1002 break; 1003 case DFS_PARAM_RELSTEP: 1004 rs->rs_param.pe_relstep = value; 1005 pe.pe_relstep = value; 1006 break; 1007 case DFS_PARAM_MAXLEN: 1008 rs->rs_param.pe_maxlen = value; 1009 pe.pe_maxlen = value; 1010 break; 1011 default: 1012 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS1, 1013 "%s: unknown threshtype (%d)\n", 1014 __func__, threshtype); 1015 break; 1016 } 1017 1018 /* 1019 * The driver layer dfs_enable routine is tasked with translating 1020 * values from the global format to the per-device (HAL, offload) 1021 * format. 1022 */ 1023 lmac_dfs_enable(dfs->dfs_pdev_obj, &is_fastclk, 1024 pe.pe_firpwr, 1025 pe.pe_rrssi, 1026 pe.pe_height, 1027 pe.pe_prssi, 1028 pe.pe_inband, 1029 pe.pe_relpwr, 1030 pe.pe_relstep, 1031 pe.pe_maxlen, 1032 dfs->dfsdomain); 1033 1034 return 1; 1035 } 1036 1037 int dfs_get_thresholds(struct wlan_dfs *dfs, 1038 struct wlan_dfs_phyerr_param *param) 1039 { 1040 qdf_mem_zero(param, sizeof(*param)); 1041 1042 lmac_dfs_get_thresholds(dfs->dfs_pdev_obj, 1043 &(param->pe_firpwr), 1044 &(param->pe_rrssi), 1045 &(param->pe_height), 1046 &(param->pe_prssi), 1047 &(param->pe_inband), 1048 &(param->pe_relpwr), 1049 &(param->pe_relstep), 1050 &(param->pe_maxlen)); 1051 1052 return 1; 1053 } 1054 1055 void dfs_set_current_channel(struct wlan_dfs *dfs, 1056 uint16_t dfs_ch_freq, 1057 uint64_t dfs_ch_flags, 1058 uint16_t dfs_ch_flagext, 1059 uint8_t dfs_ch_ieee, 1060 uint8_t dfs_ch_vhtop_ch_freq_seg1, 1061 uint8_t dfs_ch_vhtop_ch_freq_seg2) 1062 { 1063 if (dfs == NULL) { 1064 DFS_PRINTK("%s: wlan_dfs is NULL\n", __func__); 1065 return; 1066 } 1067 1068 dfs->dfs_curchan->dfs_ch_freq = dfs_ch_freq; 1069 dfs->dfs_curchan->dfs_ch_flags = dfs_ch_flags; 1070 dfs->dfs_curchan->dfs_ch_flagext = dfs_ch_flagext; 1071 dfs->dfs_curchan->dfs_ch_ieee = dfs_ch_ieee; 1072 dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg1 = dfs_ch_vhtop_ch_freq_seg1; 1073 dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2 = dfs_ch_vhtop_ch_freq_seg2; 1074 } 1075 1076 u_int dfs_ieee80211_chan2freq(struct dfs_ieee80211_channel *chan) 1077 { 1078 if (chan == NULL) 1079 return 0; 1080 1081 return chan == IEEE80211_CHAN_ANYC ? 1082 IEEE80211_CHAN_ANY : chan->dfs_ch_freq; 1083 } 1084 1085 void dfs_update_cur_chan_flags(struct wlan_dfs *dfs, 1086 uint64_t flags, 1087 uint16_t flagext) 1088 { 1089 dfs->dfs_curchan->dfs_ch_flags = flags; 1090 dfs->dfs_curchan->dfs_ch_flagext = flagext; 1091 } 1092