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