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