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