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 #include "../dfs_filter_init.h" 31 #include "../dfs_full_offload.h" 32 #include "wlan_dfs_utils_api.h" 33 #include "../dfs_etsi_precac.h" 34 #include "../dfs_partial_offload_radar.h" 35 36 #ifndef WLAN_DFS_STATIC_MEM_ALLOC 37 /* 38 * dfs_alloc_wlan_dfs() - allocate wlan_dfs buffer 39 * 40 * Return: buffer, null on failure. 41 */ 42 static inline struct wlan_dfs *dfs_alloc_wlan_dfs(void) 43 { 44 return qdf_mem_malloc(sizeof(struct wlan_dfs)); 45 } 46 47 /* 48 * dfs_free_wlan_dfs() - Free wlan_dfs buffer 49 * @dfs: wlan_dfs buffer pointer 50 * 51 * Return: None 52 */ 53 static inline void dfs_free_wlan_dfs(struct wlan_dfs *dfs) 54 { 55 qdf_mem_free(dfs); 56 } 57 58 /* 59 * dfs_alloc_dfs_curchan() - allocate dfs_channel buffer 60 * 61 * Return: buffer, null on failure. 62 */ 63 static inline struct dfs_channel *dfs_alloc_dfs_curchan(void) 64 { 65 return qdf_mem_malloc(sizeof(struct dfs_channel)); 66 } 67 68 /* 69 * dfs_free_dfs_curchan() - Free dfs_channel buffer 70 * @dfs_curchan: dfs_channel buffer pointer 71 * 72 * Return: None 73 */ 74 static inline void dfs_free_dfs_curchan(struct dfs_channel *dfs_curchan) 75 { 76 qdf_mem_free(dfs_curchan); 77 } 78 79 #else 80 81 /* Static buffers for DFS objects */ 82 static struct wlan_dfs global_dfs; 83 static struct dfs_channel global_dfs_curchan; 84 85 static inline struct wlan_dfs *dfs_alloc_wlan_dfs(void) 86 { 87 return &global_dfs; 88 } 89 90 static inline void dfs_free_wlan_dfs(struct wlan_dfs *dfs) 91 { 92 } 93 94 static inline struct dfs_channel *dfs_alloc_dfs_curchan(void) 95 { 96 return &global_dfs_curchan; 97 } 98 99 static inline void dfs_free_dfs_curchan(struct dfs_channel *dfs_curchan) 100 { 101 } 102 #endif 103 104 /** 105 * dfs_testtimer_task() - Sends CSA in the current channel. 106 * 107 * When the user sets usenol to 0 and inject the RADAR, AP does not mark the 108 * channel as RADAR and does not add the channel to NOL. It sends the CSA in 109 * the current channel. 110 */ 111 static os_timer_func(dfs_testtimer_task) 112 { 113 struct wlan_dfs *dfs = NULL; 114 115 OS_GET_TIMER_ARG(dfs, struct wlan_dfs *); 116 dfs->wlan_dfstest = 0; 117 118 /* 119 * Flip the channel back to the original channel. 120 * Make sure this is done properly with a CSA. 121 */ 122 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "go back to channel %d", 123 dfs->wlan_dfstest_ieeechan); 124 dfs_mlme_start_csa(dfs->dfs_pdev_obj, 125 dfs->wlan_dfstest_ieeechan, 126 dfs->dfs_curchan->dfs_ch_freq, 127 dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2, 128 dfs->dfs_curchan->dfs_ch_flags); 129 } 130 131 int dfs_get_debug_info(struct wlan_dfs *dfs, void *data) 132 { 133 if (data) 134 *(uint32_t *)data = dfs->dfs_proc_phyerr; 135 136 return (int)dfs->dfs_proc_phyerr; 137 } 138 139 void dfs_main_task_testtimer_init(struct wlan_dfs *dfs) 140 { 141 qdf_timer_init(NULL, 142 &(dfs->wlan_dfstesttimer), 143 dfs_testtimer_task, (void *)dfs, 144 QDF_TIMER_TYPE_WAKE_APPS); 145 } 146 147 int dfs_create_object(struct wlan_dfs **dfs) 148 { 149 *dfs = dfs_alloc_wlan_dfs(); 150 if (!(*dfs)) { 151 dfs_alert(NULL, WLAN_DEBUG_DFS_ALWAYS, 152 "wlan_dfs allocation failed"); 153 return 1; 154 } 155 156 qdf_mem_zero(*dfs, sizeof(**dfs)); 157 158 (*dfs)->dfs_curchan = dfs_alloc_dfs_curchan(); 159 if (!((*dfs)->dfs_curchan)) { 160 dfs_free_wlan_dfs(*dfs); 161 dfs_alert(*dfs, WLAN_DEBUG_DFS_ALWAYS, 162 "dfs_curchan allocation failed"); 163 return 1; 164 } 165 166 return 0; 167 } 168 169 int dfs_attach(struct wlan_dfs *dfs) 170 { 171 int ret; 172 173 if (!dfs->dfs_is_offload_enabled) { 174 ret = dfs_main_attach(dfs); 175 176 /* 177 * For full offload we have a wmi handler registered to process 178 * a radar event from firmware in the event of a radar detect. 179 * So, init of timer, dfs_task is not required for 180 * full-offload. dfs_task timer is called in 181 * dfs_main_timer_init within dfs_main_attach for 182 * partial-offload in the event of radar detect. 183 */ 184 if (ret) { 185 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs_main_attach failed"); 186 return ret; 187 } 188 } 189 dfs_cac_attach(dfs); 190 dfs_zero_cac_attach(dfs); 191 dfs_etsi_precac_attach(dfs); 192 dfs_nol_attach(dfs); 193 dfs->dfs_use_nol_subchannel_marking = 1; 194 195 /* 196 * Init of timer ,dfs_testtimer_task is required by both partial 197 * and full offload, indicating test mode timer initialization for both. 198 */ 199 dfs_main_task_testtimer_init(dfs); 200 return 0; 201 } 202 203 void dfs_stop(struct wlan_dfs *dfs) 204 { 205 dfs_nol_timer_cleanup(dfs); 206 dfs_nol_workqueue_cleanup(dfs); 207 dfs_clear_nolhistory(dfs); 208 } 209 210 void dfs_task_testtimer_reset(struct wlan_dfs *dfs) 211 { 212 if (dfs->wlan_dfstest) { 213 qdf_timer_sync_cancel(&dfs->wlan_dfstesttimer); 214 dfs->wlan_dfstest = 0; 215 } 216 } 217 218 void dfs_task_testtimer_detach(struct wlan_dfs *dfs) 219 { 220 qdf_timer_free(&dfs->wlan_dfstesttimer); 221 dfs->wlan_dfstest = 0; 222 } 223 224 void dfs_reset(struct wlan_dfs *dfs) 225 { 226 if (!dfs) { 227 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 228 return; 229 } 230 231 dfs_cac_timer_reset(dfs); 232 dfs_zero_cac_reset(dfs); 233 if (!dfs->dfs_is_offload_enabled) { 234 dfs_main_timer_reset(dfs); 235 dfs_host_wait_timer_reset(dfs); 236 dfs->dfs_event_log_count = 0; 237 } 238 dfs_task_testtimer_reset(dfs); 239 } 240 241 void dfs_timer_detach(struct wlan_dfs *dfs) 242 { 243 dfs_cac_timer_detach(dfs); 244 dfs_zero_cac_timer_detach(dfs); 245 246 if (!dfs->dfs_is_offload_enabled) { 247 dfs_main_timer_detach(dfs); 248 dfs_host_wait_timer_detach(dfs); 249 } 250 251 dfs_task_testtimer_detach(dfs); 252 dfs_nol_timer_detach(dfs); 253 } 254 255 void dfs_detach(struct wlan_dfs *dfs) 256 { 257 dfs_timer_detach(dfs); 258 if (!dfs->dfs_is_offload_enabled) 259 dfs_main_detach(dfs); 260 dfs_etsi_precac_detach(dfs); 261 dfs_zero_cac_detach(dfs); 262 dfs_nol_detach(dfs); 263 } 264 265 #ifndef WLAN_DFS_STATIC_MEM_ALLOC 266 void dfs_destroy_object(struct wlan_dfs *dfs) 267 { 268 dfs_free_dfs_curchan(dfs->dfs_curchan); 269 dfs_free_wlan_dfs(dfs); 270 } 271 #else 272 void dfs_destroy_object(struct wlan_dfs *dfs) 273 { 274 } 275 #endif 276 277 int dfs_control(struct wlan_dfs *dfs, 278 u_int id, 279 void *indata, 280 uint32_t insize, 281 void *outdata, 282 uint32_t *outsize) 283 { 284 struct wlan_dfs_phyerr_param peout; 285 struct dfs_ioctl_params *dfsparams; 286 struct dfs_bangradar_enh_params *bangradar_enh_params; 287 int error = 0; 288 uint32_t val = 0; 289 struct dfsreq_nolinfo *nol; 290 uint32_t *data = NULL; 291 int i; 292 struct dfs_emulate_bang_radar_test_cmd dfs_unit_test; 293 294 qdf_mem_zero(&dfs_unit_test, sizeof(dfs_unit_test)); 295 296 if (!dfs) { 297 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 298 goto bad; 299 } 300 301 switch (id) { 302 case DFS_SET_THRESH: 303 if (insize < sizeof(struct dfs_ioctl_params) || !indata) { 304 dfs_debug(dfs, WLAN_DEBUG_DFS1, 305 "insize = %d, expected = %zu bytes, indata = %pK", 306 insize, 307 sizeof(struct dfs_ioctl_params), 308 indata); 309 error = -EINVAL; 310 break; 311 } 312 dfsparams = (struct dfs_ioctl_params *)indata; 313 if (!dfs_set_thresholds(dfs, DFS_PARAM_FIRPWR, 314 dfsparams->dfs_firpwr)) 315 error = -EINVAL; 316 if (!dfs_set_thresholds(dfs, DFS_PARAM_RRSSI, 317 dfsparams->dfs_rrssi)) 318 error = -EINVAL; 319 if (!dfs_set_thresholds(dfs, DFS_PARAM_HEIGHT, 320 dfsparams->dfs_height)) 321 error = -EINVAL; 322 if (!dfs_set_thresholds(dfs, DFS_PARAM_PRSSI, 323 dfsparams->dfs_prssi)) 324 error = -EINVAL; 325 if (!dfs_set_thresholds(dfs, DFS_PARAM_INBAND, 326 dfsparams->dfs_inband)) 327 error = -EINVAL; 328 329 /* 5413 speicfic. */ 330 if (!dfs_set_thresholds(dfs, DFS_PARAM_RELPWR, 331 dfsparams->dfs_relpwr)) 332 error = -EINVAL; 333 if (!dfs_set_thresholds(dfs, DFS_PARAM_RELSTEP, 334 dfsparams->dfs_relstep)) 335 error = -EINVAL; 336 if (!dfs_set_thresholds(dfs, DFS_PARAM_MAXLEN, 337 dfsparams->dfs_maxlen)) 338 error = -EINVAL; 339 break; 340 case DFS_BANGRADAR_ENH: 341 if (insize < sizeof(struct dfs_bangradar_enh_params) || 342 !indata) { 343 dfs_debug(dfs, WLAN_DEBUG_DFS1, 344 "insize = %d, expected = %zu bytes, indata = %pK", 345 insize, 346 sizeof(struct dfs_bangradar_enh_params), 347 indata); 348 error = -EINVAL; 349 break; 350 } 351 bangradar_enh_params = 352 (struct dfs_bangradar_enh_params *)indata; 353 if (bangradar_enh_params) { 354 dfs->dfs_seg_id = bangradar_enh_params->seg_id; 355 dfs->dfs_is_chirp = bangradar_enh_params->is_chirp; 356 dfs->dfs_freq_offset = 357 bangradar_enh_params->freq_offset; 358 359 if (dfs->dfs_is_offload_enabled) { 360 error = dfs_fill_emulate_bang_radar_test 361 (dfs, SEG_ID_PRIMARY, 362 &dfs_unit_test); 363 } else { 364 dfs->dfs_bangradar = 1; 365 error = dfs_start_host_based_bangradar(dfs); 366 } 367 } else { 368 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "bangradar_enh_params is NULL"); 369 } 370 371 break; 372 case DFS_GET_THRESH: 373 if (!outdata || !outsize || 374 *outsize < sizeof(struct dfs_ioctl_params)) { 375 error = -EINVAL; 376 break; 377 } 378 *outsize = sizeof(struct dfs_ioctl_params); 379 dfsparams = (struct dfs_ioctl_params *) outdata; 380 381 /* Fetch the DFS thresholds using the internal representation */ 382 (void) dfs_get_thresholds(dfs, &peout); 383 384 /* Convert them to the dfs IOCTL representation. */ 385 wlan_dfs_dfsparam_to_ioctlparam(&peout, dfsparams); 386 break; 387 case DFS_RADARDETECTS: 388 if (!outdata || !outsize || *outsize < sizeof(uint32_t)) { 389 error = -EINVAL; 390 break; 391 } 392 *outsize = sizeof(uint32_t); 393 *((uint32_t *)outdata) = dfs->wlan_dfs_stats.num_radar_detects; 394 break; 395 case DFS_DISABLE_DETECT: 396 dfs->dfs_proc_phyerr &= ~DFS_RADAR_EN; 397 dfs->dfs_proc_phyerr &= ~DFS_SECOND_SEGMENT_RADAR_EN; 398 dfs->dfs_ignore_dfs = 1; 399 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 400 "enable detects, ignore_dfs %d", 401 dfs->dfs_ignore_dfs ? 1:0); 402 break; 403 case DFS_ENABLE_DETECT: 404 dfs->dfs_proc_phyerr |= DFS_RADAR_EN; 405 dfs->dfs_proc_phyerr |= DFS_SECOND_SEGMENT_RADAR_EN; 406 dfs->dfs_ignore_dfs = 0; 407 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS 408 , "enable detects, ignore_dfs %d", 409 dfs->dfs_ignore_dfs ? 1:0); 410 break; 411 case DFS_DISABLE_FFT: 412 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 413 "TODO disable FFT val=0x%x", val); 414 break; 415 case DFS_ENABLE_FFT: 416 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 417 "TODO enable FFT val=0x%x", val); 418 break; 419 case DFS_SET_DEBUG_LEVEL: 420 if (insize < sizeof(uint32_t) || !indata) { 421 error = -EINVAL; 422 break; 423 } 424 dfs->dfs_debug_mask = *(uint32_t *)indata; 425 426 /* Do not allow user to set the ALWAYS/MAX bit. 427 * It will be used internally by dfs print macro(s) 428 * to print messages when dfs is NULL. 429 */ 430 dfs->dfs_debug_mask &= ~(WLAN_DEBUG_DFS_ALWAYS); 431 432 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 433 "debug level now = 0x%x", dfs->dfs_debug_mask); 434 if (dfs->dfs_debug_mask & WLAN_DEBUG_DFS3) { 435 /* Enable debug Radar Event */ 436 dfs->dfs_event_log_on = 1; 437 } else if ((utils_get_dfsdomain(dfs->dfs_pdev_obj) == 438 DFS_FCC_DOMAIN) && 439 lmac_is_host_dfs_check_support_enabled(dfs->dfs_pdev_obj)) { 440 dfs->dfs_event_log_on = 1; 441 } else { 442 dfs->dfs_event_log_on = 0; 443 } 444 break; 445 case DFS_SET_FALSE_RSSI_THRES: 446 if (insize < sizeof(uint32_t) || !indata) { 447 error = -EINVAL; 448 break; 449 } 450 dfs->wlan_dfs_false_rssi_thres = *(uint32_t *)indata; 451 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 452 "false RSSI threshold now = 0x%x", 453 dfs->wlan_dfs_false_rssi_thres); 454 break; 455 case DFS_SET_PEAK_MAG: 456 if (insize < sizeof(uint32_t) || !indata) { 457 error = -EINVAL; 458 break; 459 } 460 dfs->wlan_dfs_peak_mag = *(uint32_t *)indata; 461 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 462 "peak_mag now = 0x%x", 463 dfs->wlan_dfs_peak_mag); 464 break; 465 case DFS_GET_CAC_VALID_TIME: 466 if (!outdata || !outsize || *outsize < sizeof(uint32_t)) { 467 error = -EINVAL; 468 break; 469 } 470 *outsize = sizeof(uint32_t); 471 *((uint32_t *)outdata) = dfs->dfs_cac_valid_time; 472 break; 473 case DFS_SET_CAC_VALID_TIME: 474 if (insize < sizeof(uint32_t) || !indata) { 475 error = -EINVAL; 476 break; 477 } 478 dfs->dfs_cac_valid_time = *(uint32_t *)indata; 479 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 480 "dfs timeout = %d", dfs->dfs_cac_valid_time); 481 break; 482 case DFS_IGNORE_CAC: 483 if (insize < sizeof(uint32_t) || !indata) { 484 error = -EINVAL; 485 break; 486 } 487 488 if (*(uint32_t *)indata) 489 dfs->dfs_ignore_cac = 1; 490 else 491 dfs->dfs_ignore_cac = 0; 492 493 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 494 "ignore cac = 0x%x", dfs->dfs_ignore_cac); 495 break; 496 case DFS_SET_NOL_TIMEOUT: 497 if (insize < sizeof(uint32_t) || !indata) { 498 error = -EINVAL; 499 break; 500 } 501 if (*(int *)indata) 502 dfs->wlan_dfs_nol_timeout = *(int *)indata; 503 else 504 dfs->wlan_dfs_nol_timeout = DFS_NOL_TIMEOUT_S; 505 506 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "nol timeout = %d sec", 507 dfs->wlan_dfs_nol_timeout); 508 break; 509 case DFS_MUTE_TIME: 510 if (insize < sizeof(uint32_t) || !indata) { 511 error = -EINVAL; 512 break; 513 } 514 data = (uint32_t *) indata; 515 dfs->wlan_dfstesttime = *data; 516 dfs->wlan_dfstesttime *= (1000); /* convert sec into ms */ 517 break; 518 case DFS_GET_USENOL: 519 if (!outdata || !outsize || *outsize < sizeof(uint32_t)) { 520 error = -EINVAL; 521 break; 522 } 523 *outsize = sizeof(uint32_t); 524 *((uint32_t *)outdata) = dfs->dfs_use_nol; 525 526 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 527 "#Phyerr=%d, #false detect=%d, #queued=%d", 528 dfs->dfs_phyerr_count, 529 dfs->dfs_phyerr_reject_count, 530 dfs->dfs_phyerr_queued_count); 531 532 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 533 "dfs_phyerr_freq_min=%d, dfs_phyerr_freq_max=%d", 534 dfs->dfs_phyerr_freq_min, 535 dfs->dfs_phyerr_freq_max); 536 537 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 538 "Total radar events detected=%d, entries in the radar queue follows:", 539 dfs->dfs_event_log_count); 540 541 for (i = 0; (i < DFS_EVENT_LOG_SIZE) && 542 (i < dfs->dfs_event_log_count); i++) { 543 #define FREQ_OFFSET1 ((int)dfs->radar_log[i].freq_offset_khz / 1000) 544 #define FREQ_OFFSET2 ((int)abs(dfs->radar_log[i].freq_offset_khz) % 1000) 545 dfs_debug(dfs, WLAN_DEBUG_DFS, 546 "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\n", 547 dfs->radar_log[i].ts, 548 dfs->radar_log[i].diff_ts, 549 dfs->radar_log[i].rssi, 550 dfs->radar_log[i].dur, 551 dfs->radar_log[i].is_chirp, 552 dfs->radar_log[i].seg_id, 553 dfs->radar_log[i].sidx, 554 FREQ_OFFSET1, 555 FREQ_OFFSET2, 556 dfs->radar_log[i].peak_mag, 557 dfs->radar_log[i].total_gain, 558 dfs->radar_log[i].mb_gain, 559 dfs->radar_log[i].relpwr_db, 560 dfs->radar_log[i].delta_diff, 561 dfs->radar_log[i].delta_peak, 562 dfs->radar_log[i].psidx_diff); 563 } 564 dfs->dfs_event_log_count = 0; 565 dfs->dfs_phyerr_count = 0; 566 dfs->dfs_phyerr_reject_count = 0; 567 dfs->dfs_phyerr_queued_count = 0; 568 dfs->dfs_phyerr_freq_min = 0x7fffffff; 569 dfs->dfs_phyerr_freq_max = 0; 570 break; 571 case DFS_SET_USENOL: 572 if (insize < sizeof(uint32_t) || !indata) { 573 error = -EINVAL; 574 break; 575 } 576 dfs->dfs_use_nol = *(uint32_t *)indata; 577 break; 578 case DFS_GET_NOL: 579 if (!outdata || !outsize || 580 *outsize < sizeof(struct dfsreq_nolinfo)) { 581 error = -EINVAL; 582 break; 583 } 584 *outsize = sizeof(struct dfsreq_nolinfo); 585 nol = (struct dfsreq_nolinfo *)outdata; 586 DFS_GET_NOL_LOCKED(dfs, 587 (struct dfsreq_nolelem *)nol->dfs_nol, 588 &nol->dfs_ch_nchans); 589 DFS_PRINT_NOL_LOCKED(dfs); 590 break; 591 case DFS_SET_NOL: 592 if (insize < sizeof(struct dfsreq_nolinfo) || !indata) { 593 error = -EINVAL; 594 break; 595 } 596 nol = (struct dfsreq_nolinfo *) indata; 597 dfs_set_nol(dfs, 598 (struct dfsreq_nolelem *)nol->dfs_nol, 599 nol->dfs_ch_nchans); 600 break; 601 case DFS_SHOW_NOL: 602 DFS_PRINT_NOL_LOCKED(dfs); 603 break; 604 case DFS_SHOW_NOLHISTORY: 605 dfs_print_nolhistory(dfs); 606 break; 607 case DFS_BANGRADAR: 608 if (dfs->dfs_is_offload_enabled) { 609 error = dfs_fill_emulate_bang_radar_test(dfs, 610 SEG_ID_PRIMARY, 611 &dfs_unit_test); 612 } else { 613 dfs->dfs_bangradar = 1; 614 error = dfs_start_host_based_bangradar(dfs); 615 } 616 break; 617 case DFS_SHOW_PRECAC_LISTS: 618 dfs_print_precaclists(dfs); 619 dfs_print_etsi_precaclists(dfs); 620 break; 621 case DFS_RESET_PRECAC_LISTS: 622 dfs_reset_precac_lists(dfs); 623 dfs_reset_etsi_precac_lists(dfs); 624 break; 625 case DFS_SECOND_SEGMENT_BANGRADAR: 626 if (dfs->dfs_is_offload_enabled) { 627 error = dfs_fill_emulate_bang_radar_test(dfs, 628 SEG_ID_SECONDARY, 629 &dfs_unit_test); 630 } else { 631 dfs->dfs_second_segment_bangradar = 1; 632 error = dfs_start_host_based_bangradar(dfs); 633 } 634 break; 635 default: 636 error = -EINVAL; 637 } 638 639 bad: 640 return error; 641 } 642 643 void dfs_set_current_channel(struct wlan_dfs *dfs, 644 uint16_t dfs_ch_freq, 645 uint64_t dfs_ch_flags, 646 uint16_t dfs_ch_flagext, 647 uint8_t dfs_ch_ieee, 648 uint8_t dfs_ch_vhtop_ch_freq_seg1, 649 uint8_t dfs_ch_vhtop_ch_freq_seg2) 650 { 651 if (!dfs) { 652 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 653 return; 654 } 655 656 dfs->dfs_curchan->dfs_ch_freq = dfs_ch_freq; 657 dfs->dfs_curchan->dfs_ch_flags = dfs_ch_flags; 658 dfs->dfs_curchan->dfs_ch_flagext = dfs_ch_flagext; 659 dfs->dfs_curchan->dfs_ch_ieee = dfs_ch_ieee; 660 dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg1 = dfs_ch_vhtop_ch_freq_seg1; 661 dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2 = dfs_ch_vhtop_ch_freq_seg2; 662 } 663 664 void dfs_update_cur_chan_flags(struct wlan_dfs *dfs, 665 uint64_t flags, 666 uint16_t flagext) 667 { 668 dfs->dfs_curchan->dfs_ch_flags = flags; 669 dfs->dfs_curchan->dfs_ch_flagext = flagext; 670 } 671