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