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 dfs->dfs_enhanced_bangradar = 1; 359 360 if (dfs->dfs_is_offload_enabled) { 361 error = dfs_fill_emulate_bang_radar_test 362 (dfs, SEG_ID_PRIMARY, 363 &dfs_unit_test); 364 } else { 365 dfs->dfs_bangradar = 1; 366 error = dfs_start_host_based_bangradar(dfs); 367 } 368 } else { 369 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "bangradar_enh_params is NULL"); 370 } 371 372 break; 373 case DFS_GET_THRESH: 374 if (!outdata || !outsize || 375 *outsize < sizeof(struct dfs_ioctl_params)) { 376 error = -EINVAL; 377 break; 378 } 379 *outsize = sizeof(struct dfs_ioctl_params); 380 dfsparams = (struct dfs_ioctl_params *) outdata; 381 382 /* Fetch the DFS thresholds using the internal representation */ 383 (void) dfs_get_thresholds(dfs, &peout); 384 385 /* Convert them to the dfs IOCTL representation. */ 386 wlan_dfs_dfsparam_to_ioctlparam(&peout, dfsparams); 387 break; 388 case DFS_RADARDETECTS: 389 if (!outdata || !outsize || *outsize < sizeof(uint32_t)) { 390 error = -EINVAL; 391 break; 392 } 393 *outsize = sizeof(uint32_t); 394 *((uint32_t *)outdata) = dfs->wlan_dfs_stats.num_radar_detects; 395 break; 396 case DFS_DISABLE_DETECT: 397 dfs->dfs_proc_phyerr &= ~DFS_RADAR_EN; 398 dfs->dfs_proc_phyerr &= ~DFS_SECOND_SEGMENT_RADAR_EN; 399 dfs->dfs_ignore_dfs = 1; 400 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 401 "enable detects, ignore_dfs %d", 402 dfs->dfs_ignore_dfs ? 1:0); 403 break; 404 case DFS_ENABLE_DETECT: 405 dfs->dfs_proc_phyerr |= DFS_RADAR_EN; 406 dfs->dfs_proc_phyerr |= DFS_SECOND_SEGMENT_RADAR_EN; 407 dfs->dfs_ignore_dfs = 0; 408 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS 409 , "enable detects, ignore_dfs %d", 410 dfs->dfs_ignore_dfs ? 1:0); 411 break; 412 case DFS_DISABLE_FFT: 413 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 414 "TODO disable FFT val=0x%x", val); 415 break; 416 case DFS_ENABLE_FFT: 417 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 418 "TODO enable FFT val=0x%x", val); 419 break; 420 case DFS_SET_DEBUG_LEVEL: 421 if (insize < sizeof(uint32_t) || !indata) { 422 error = -EINVAL; 423 break; 424 } 425 dfs->dfs_debug_mask = *(uint32_t *)indata; 426 427 /* Do not allow user to set the ALWAYS/MAX bit. 428 * It will be used internally by dfs print macro(s) 429 * to print messages when dfs is NULL. 430 */ 431 dfs->dfs_debug_mask &= ~(WLAN_DEBUG_DFS_ALWAYS); 432 433 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 434 "debug level now = 0x%x", dfs->dfs_debug_mask); 435 if (dfs->dfs_debug_mask & WLAN_DEBUG_DFS3) { 436 /* Enable debug Radar Event */ 437 dfs->dfs_event_log_on = 1; 438 } else if ((utils_get_dfsdomain(dfs->dfs_pdev_obj) == 439 DFS_FCC_DOMAIN) && 440 lmac_is_host_dfs_check_support_enabled(dfs->dfs_pdev_obj)) { 441 dfs->dfs_event_log_on = 1; 442 } else { 443 dfs->dfs_event_log_on = 0; 444 } 445 break; 446 case DFS_SET_FALSE_RSSI_THRES: 447 if (insize < sizeof(uint32_t) || !indata) { 448 error = -EINVAL; 449 break; 450 } 451 dfs->wlan_dfs_false_rssi_thres = *(uint32_t *)indata; 452 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 453 "false RSSI threshold now = 0x%x", 454 dfs->wlan_dfs_false_rssi_thres); 455 break; 456 case DFS_SET_PEAK_MAG: 457 if (insize < sizeof(uint32_t) || !indata) { 458 error = -EINVAL; 459 break; 460 } 461 dfs->wlan_dfs_peak_mag = *(uint32_t *)indata; 462 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 463 "peak_mag now = 0x%x", 464 dfs->wlan_dfs_peak_mag); 465 break; 466 case DFS_GET_CAC_VALID_TIME: 467 if (!outdata || !outsize || *outsize < sizeof(uint32_t)) { 468 error = -EINVAL; 469 break; 470 } 471 *outsize = sizeof(uint32_t); 472 *((uint32_t *)outdata) = dfs->dfs_cac_valid_time; 473 break; 474 case DFS_SET_CAC_VALID_TIME: 475 if (insize < sizeof(uint32_t) || !indata) { 476 error = -EINVAL; 477 break; 478 } 479 dfs->dfs_cac_valid_time = *(uint32_t *)indata; 480 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 481 "dfs timeout = %d", dfs->dfs_cac_valid_time); 482 break; 483 case DFS_IGNORE_CAC: 484 if (insize < sizeof(uint32_t) || !indata) { 485 error = -EINVAL; 486 break; 487 } 488 489 if (*(uint32_t *)indata) 490 dfs->dfs_ignore_cac = 1; 491 else 492 dfs->dfs_ignore_cac = 0; 493 494 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 495 "ignore cac = 0x%x", dfs->dfs_ignore_cac); 496 break; 497 case DFS_SET_NOL_TIMEOUT: 498 if (insize < sizeof(uint32_t) || !indata) { 499 error = -EINVAL; 500 break; 501 } 502 if (*(int *)indata) 503 dfs->wlan_dfs_nol_timeout = *(int *)indata; 504 else 505 dfs->wlan_dfs_nol_timeout = DFS_NOL_TIMEOUT_S; 506 507 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "nol timeout = %d sec", 508 dfs->wlan_dfs_nol_timeout); 509 break; 510 case DFS_MUTE_TIME: 511 if (insize < sizeof(uint32_t) || !indata) { 512 error = -EINVAL; 513 break; 514 } 515 data = (uint32_t *) indata; 516 dfs->wlan_dfstesttime = *data; 517 dfs->wlan_dfstesttime *= (1000); /* convert sec into ms */ 518 break; 519 case DFS_GET_USENOL: 520 if (!outdata || !outsize || *outsize < sizeof(uint32_t)) { 521 error = -EINVAL; 522 break; 523 } 524 *outsize = sizeof(uint32_t); 525 *((uint32_t *)outdata) = dfs->dfs_use_nol; 526 527 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 528 "#Phyerr=%d, #false detect=%d, #queued=%d", 529 dfs->dfs_phyerr_count, 530 dfs->dfs_phyerr_reject_count, 531 dfs->dfs_phyerr_queued_count); 532 533 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 534 "dfs_phyerr_freq_min=%d, dfs_phyerr_freq_max=%d", 535 dfs->dfs_phyerr_freq_min, 536 dfs->dfs_phyerr_freq_max); 537 538 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 539 "Total radar events detected=%d, entries in the radar queue follows:", 540 dfs->dfs_event_log_count); 541 542 for (i = 0; (i < DFS_EVENT_LOG_SIZE) && 543 (i < dfs->dfs_event_log_count); i++) { 544 #define FREQ_OFFSET1 ((int)dfs->radar_log[i].freq_offset_khz / 1000) 545 #define FREQ_OFFSET2 ((int)abs(dfs->radar_log[i].freq_offset_khz) % 1000) 546 dfs_debug(dfs, WLAN_DEBUG_DFS, 547 "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", 548 dfs->radar_log[i].ts, 549 dfs->radar_log[i].diff_ts, 550 dfs->radar_log[i].rssi, 551 dfs->radar_log[i].dur, 552 dfs->radar_log[i].is_chirp, 553 dfs->radar_log[i].seg_id, 554 dfs->radar_log[i].sidx, 555 FREQ_OFFSET1, 556 FREQ_OFFSET2, 557 dfs->radar_log[i].peak_mag, 558 dfs->radar_log[i].total_gain, 559 dfs->radar_log[i].mb_gain, 560 dfs->radar_log[i].relpwr_db, 561 dfs->radar_log[i].delta_diff, 562 dfs->radar_log[i].delta_peak, 563 dfs->radar_log[i].psidx_diff); 564 } 565 dfs->dfs_event_log_count = 0; 566 dfs->dfs_phyerr_count = 0; 567 dfs->dfs_phyerr_reject_count = 0; 568 dfs->dfs_phyerr_queued_count = 0; 569 dfs->dfs_phyerr_freq_min = 0x7fffffff; 570 dfs->dfs_phyerr_freq_max = 0; 571 break; 572 case DFS_SET_USENOL: 573 if (insize < sizeof(uint32_t) || !indata) { 574 error = -EINVAL; 575 break; 576 } 577 dfs->dfs_use_nol = *(uint32_t *)indata; 578 break; 579 case DFS_GET_NOL: 580 if (!outdata || !outsize || 581 *outsize < sizeof(struct dfsreq_nolinfo)) { 582 error = -EINVAL; 583 break; 584 } 585 *outsize = sizeof(struct dfsreq_nolinfo); 586 nol = (struct dfsreq_nolinfo *)outdata; 587 DFS_GET_NOL_LOCKED(dfs, 588 (struct dfsreq_nolelem *)nol->dfs_nol, 589 &nol->dfs_ch_nchans); 590 DFS_PRINT_NOL_LOCKED(dfs); 591 break; 592 case DFS_SET_NOL: 593 if (insize < sizeof(struct dfsreq_nolinfo) || !indata) { 594 error = -EINVAL; 595 break; 596 } 597 nol = (struct dfsreq_nolinfo *) indata; 598 dfs_set_nol(dfs, 599 (struct dfsreq_nolelem *)nol->dfs_nol, 600 nol->dfs_ch_nchans); 601 break; 602 case DFS_SHOW_NOL: 603 DFS_PRINT_NOL_LOCKED(dfs); 604 break; 605 case DFS_SHOW_NOLHISTORY: 606 dfs_print_nolhistory(dfs); 607 break; 608 case DFS_BANGRADAR: 609 if (dfs->dfs_is_offload_enabled) { 610 error = dfs_fill_emulate_bang_radar_test(dfs, 611 SEG_ID_PRIMARY, 612 &dfs_unit_test); 613 } else { 614 dfs->dfs_bangradar = 1; 615 error = dfs_start_host_based_bangradar(dfs); 616 } 617 break; 618 case DFS_SHOW_PRECAC_LISTS: 619 dfs_print_precaclists(dfs); 620 dfs_print_etsi_precaclists(dfs); 621 break; 622 case DFS_RESET_PRECAC_LISTS: 623 dfs_reset_precac_lists(dfs); 624 dfs_reset_etsi_precac_lists(dfs); 625 break; 626 case DFS_SECOND_SEGMENT_BANGRADAR: 627 if (dfs->dfs_is_offload_enabled) { 628 error = dfs_fill_emulate_bang_radar_test(dfs, 629 SEG_ID_SECONDARY, 630 &dfs_unit_test); 631 } else { 632 dfs->dfs_second_segment_bangradar = 1; 633 error = dfs_start_host_based_bangradar(dfs); 634 } 635 break; 636 default: 637 error = -EINVAL; 638 } 639 640 bad: 641 return error; 642 } 643 644 void dfs_set_current_channel(struct wlan_dfs *dfs, 645 uint16_t dfs_ch_freq, 646 uint64_t dfs_ch_flags, 647 uint16_t dfs_ch_flagext, 648 uint8_t dfs_ch_ieee, 649 uint8_t dfs_ch_vhtop_ch_freq_seg1, 650 uint8_t dfs_ch_vhtop_ch_freq_seg2) 651 { 652 if (!dfs) { 653 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 654 return; 655 } 656 657 dfs->dfs_curchan->dfs_ch_freq = dfs_ch_freq; 658 dfs->dfs_curchan->dfs_ch_flags = dfs_ch_flags; 659 dfs->dfs_curchan->dfs_ch_flagext = dfs_ch_flagext; 660 dfs->dfs_curchan->dfs_ch_ieee = dfs_ch_ieee; 661 dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg1 = dfs_ch_vhtop_ch_freq_seg1; 662 dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2 = dfs_ch_vhtop_ch_freq_seg2; 663 } 664 665 void dfs_update_cur_chan_flags(struct wlan_dfs *dfs, 666 uint64_t flags, 667 uint16_t flagext) 668 { 669 dfs->dfs_curchan->dfs_ch_flags = flags; 670 dfs->dfs_curchan->dfs_ch_flagext = flagext; 671 } 672