1 /* 2 * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. 3 * 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /** 21 * DOC: This file has the DFS dispatcher API implementation which is exposed 22 * to outside of DFS component. 23 */ 24 #include "wlan_dfs_utils_api.h" 25 #include "../../core/src/dfs.h" 26 #include "../../core/src/dfs_zero_cac.h" 27 #include <wlan_reg_services_api.h> 28 #include "../../core/src/dfs_random_chan_sel.h" 29 #ifdef QCA_DFS_USE_POLICY_MANAGER 30 #include "wlan_policy_mgr_api.h" 31 #endif 32 #ifdef QCA_DFS_NOL_PLATFORM_DRV_SUPPORT 33 #include <pld_common.h> 34 #endif 35 #include <qdf_module.h> 36 37 struct dfs_nol_info { 38 uint16_t num_chans; 39 struct dfsreq_nolelem dfs_nol[DFS_MAX_NOL_CHANNEL]; 40 }; 41 42 QDF_STATUS utils_dfs_reset(struct wlan_objmgr_pdev *pdev) 43 { 44 struct wlan_dfs *dfs; 45 46 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 47 if (!dfs) 48 return QDF_STATUS_E_FAILURE; 49 50 dfs_reset(dfs); 51 dfs_nol_update(dfs); 52 dfs_reset_precaclists(dfs); 53 54 return QDF_STATUS_SUCCESS; 55 } 56 57 QDF_STATUS utils_dfs_cac_valid_reset(struct wlan_objmgr_pdev *pdev, 58 uint8_t prevchan_ieee, 59 uint32_t prevchan_flags) 60 { 61 struct wlan_dfs *dfs; 62 63 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 64 if (!dfs) 65 return QDF_STATUS_E_FAILURE; 66 67 dfs_cac_valid_reset(dfs, prevchan_ieee, prevchan_flags); 68 69 return QDF_STATUS_SUCCESS; 70 } 71 qdf_export_symbol(utils_dfs_cac_valid_reset); 72 73 QDF_STATUS utils_dfs_reset_precaclists(struct wlan_objmgr_pdev *pdev) 74 { 75 struct wlan_dfs *dfs; 76 77 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 78 if (!dfs) 79 return QDF_STATUS_E_FAILURE; 80 81 dfs_reset_precaclists(dfs); 82 83 return QDF_STATUS_SUCCESS; 84 } 85 qdf_export_symbol(utils_dfs_reset_precaclists); 86 87 QDF_STATUS utils_dfs_cancel_precac_timer(struct wlan_objmgr_pdev *pdev) 88 { 89 struct wlan_dfs *dfs; 90 91 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 92 if (!dfs) 93 return QDF_STATUS_E_FAILURE; 94 95 dfs_cancel_precac_timer(dfs); 96 97 return QDF_STATUS_SUCCESS; 98 } 99 qdf_export_symbol(utils_dfs_cancel_precac_timer); 100 101 QDF_STATUS utils_dfs_is_precac_done(struct wlan_objmgr_pdev *pdev, 102 bool *is_precac_done) 103 { 104 struct wlan_dfs *dfs; 105 106 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 107 if (!dfs) 108 return QDF_STATUS_E_FAILURE; 109 110 *is_precac_done = dfs_is_precac_done(dfs); 111 112 return QDF_STATUS_SUCCESS; 113 } 114 qdf_export_symbol(utils_dfs_is_precac_done); 115 116 QDF_STATUS utils_dfs_cancel_cac_timer(struct wlan_objmgr_pdev *pdev) 117 { 118 struct wlan_dfs *dfs; 119 120 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 121 if (!dfs) 122 return QDF_STATUS_E_FAILURE; 123 124 dfs_cancel_cac_timer(dfs); 125 126 return QDF_STATUS_SUCCESS; 127 } 128 qdf_export_symbol(utils_dfs_cancel_cac_timer); 129 130 QDF_STATUS utils_dfs_start_cac_timer(struct wlan_objmgr_pdev *pdev) 131 { 132 struct wlan_dfs *dfs; 133 134 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 135 if (!dfs) 136 return QDF_STATUS_E_FAILURE; 137 138 dfs_start_cac_timer(dfs); 139 140 return QDF_STATUS_SUCCESS; 141 } 142 qdf_export_symbol(utils_dfs_start_cac_timer); 143 144 QDF_STATUS utils_dfs_cac_stop(struct wlan_objmgr_pdev *pdev) 145 { 146 struct wlan_dfs *dfs; 147 148 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 149 if (!dfs) 150 return QDF_STATUS_E_FAILURE; 151 152 dfs_cac_stop(dfs); 153 return QDF_STATUS_SUCCESS; 154 } 155 qdf_export_symbol(utils_dfs_cac_stop); 156 157 QDF_STATUS utils_dfs_stacac_stop(struct wlan_objmgr_pdev *pdev) 158 { 159 struct wlan_dfs *dfs; 160 161 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 162 if (!dfs) 163 return QDF_STATUS_E_FAILURE; 164 165 dfs_stacac_stop(dfs); 166 167 return QDF_STATUS_SUCCESS; 168 } 169 qdf_export_symbol(utils_dfs_stacac_stop); 170 171 QDF_STATUS utils_dfs_get_usenol(struct wlan_objmgr_pdev *pdev, uint16_t *usenol) 172 { 173 struct wlan_dfs *dfs; 174 175 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 176 if (!dfs) 177 return QDF_STATUS_E_FAILURE; 178 179 *usenol = dfs_get_use_nol(dfs); 180 181 return QDF_STATUS_SUCCESS; 182 } 183 qdf_export_symbol(utils_dfs_get_usenol); 184 185 QDF_STATUS utils_dfs_radar_disable(struct wlan_objmgr_pdev *pdev) 186 { 187 struct wlan_dfs *dfs; 188 189 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 190 if (!dfs) 191 return QDF_STATUS_E_FAILURE; 192 193 dfs_radar_disable(dfs); 194 195 return QDF_STATUS_SUCCESS; 196 } 197 qdf_export_symbol(utils_dfs_radar_disable); 198 199 QDF_STATUS utils_dfs_set_update_nol_flag(struct wlan_objmgr_pdev *pdev, 200 bool val) 201 { 202 struct wlan_dfs *dfs; 203 204 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 205 if (!dfs) 206 return QDF_STATUS_E_FAILURE; 207 208 dfs_set_update_nol_flag(dfs, val); 209 210 return QDF_STATUS_SUCCESS; 211 } 212 qdf_export_symbol(utils_dfs_set_update_nol_flag); 213 214 QDF_STATUS utils_dfs_get_update_nol_flag(struct wlan_objmgr_pdev *pdev, 215 bool *nol_flag) 216 { 217 struct wlan_dfs *dfs; 218 219 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 220 if (!dfs) 221 return QDF_STATUS_E_FAILURE; 222 223 *nol_flag = dfs_get_update_nol_flag(dfs); 224 225 return QDF_STATUS_SUCCESS; 226 } 227 qdf_export_symbol(utils_dfs_get_update_nol_flag); 228 229 QDF_STATUS utils_dfs_get_dfs_use_nol(struct wlan_objmgr_pdev *pdev, 230 int *dfs_use_nol) 231 { 232 struct wlan_dfs *dfs; 233 234 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 235 if (!dfs) 236 return QDF_STATUS_E_FAILURE; 237 238 *dfs_use_nol = dfs_get_use_nol(dfs); 239 240 return QDF_STATUS_SUCCESS; 241 } 242 qdf_export_symbol(utils_dfs_get_dfs_use_nol); 243 244 QDF_STATUS utils_dfs_get_nol_timeout(struct wlan_objmgr_pdev *pdev, 245 int *dfs_nol_timeout) 246 { 247 struct wlan_dfs *dfs; 248 249 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 250 if (!dfs) 251 return QDF_STATUS_E_FAILURE; 252 253 *dfs_nol_timeout = dfs_get_nol_timeout(dfs); 254 255 return QDF_STATUS_SUCCESS; 256 } 257 qdf_export_symbol(utils_dfs_get_nol_timeout); 258 259 QDF_STATUS utils_dfs_nol_addchan(struct wlan_objmgr_pdev *pdev, 260 uint16_t freq, 261 uint32_t dfs_nol_timeout) 262 { 263 struct wlan_dfs *dfs; 264 265 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 266 if (!dfs) 267 return QDF_STATUS_E_FAILURE; 268 269 DFS_NOL_ADD_CHAN_LOCKED(dfs, freq, dfs_nol_timeout); 270 271 return QDF_STATUS_SUCCESS; 272 } 273 qdf_export_symbol(utils_dfs_nol_addchan); 274 275 QDF_STATUS utils_dfs_nol_update(struct wlan_objmgr_pdev *pdev) 276 { 277 struct wlan_dfs *dfs; 278 279 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 280 if (!dfs) 281 return QDF_STATUS_E_FAILURE; 282 283 dfs_nol_update(dfs); 284 285 return QDF_STATUS_SUCCESS; 286 } 287 qdf_export_symbol(utils_dfs_nol_update); 288 289 QDF_STATUS utils_dfs_second_segment_radar_disable(struct wlan_objmgr_pdev *pdev) 290 { 291 struct wlan_dfs *dfs; 292 293 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 294 if (!dfs) 295 return QDF_STATUS_E_FAILURE; 296 297 dfs_second_segment_radar_disable(dfs); 298 299 return QDF_STATUS_SUCCESS; 300 } 301 302 QDF_STATUS utils_dfs_is_ignore_dfs(struct wlan_objmgr_pdev *pdev, 303 bool *ignore_dfs) 304 { 305 struct wlan_dfs *dfs; 306 307 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 308 if (!dfs) 309 return QDF_STATUS_E_FAILURE; 310 311 *ignore_dfs = dfs->dfs_ignore_dfs; 312 313 return QDF_STATUS_SUCCESS; 314 } 315 qdf_export_symbol(utils_dfs_is_ignore_dfs); 316 317 QDF_STATUS utils_dfs_is_cac_valid(struct wlan_objmgr_pdev *pdev, 318 bool *is_cac_valid) 319 { 320 struct wlan_dfs *dfs; 321 322 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 323 if (!dfs) 324 return QDF_STATUS_E_FAILURE; 325 326 *is_cac_valid = dfs->dfs_cac_valid; 327 328 return QDF_STATUS_SUCCESS; 329 } 330 qdf_export_symbol(utils_dfs_is_cac_valid); 331 332 QDF_STATUS utils_dfs_is_ignore_cac(struct wlan_objmgr_pdev *pdev, 333 bool *ignore_cac) 334 { 335 struct wlan_dfs *dfs; 336 337 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 338 if (!dfs) 339 return QDF_STATUS_E_FAILURE; 340 341 *ignore_cac = dfs->dfs_ignore_cac; 342 343 return QDF_STATUS_SUCCESS; 344 } 345 qdf_export_symbol(utils_dfs_is_ignore_cac); 346 347 QDF_STATUS utils_dfs_set_cac_timer_running(struct wlan_objmgr_pdev *pdev, 348 int val) 349 { 350 struct wlan_dfs *dfs; 351 352 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 353 if (!dfs) 354 return QDF_STATUS_E_FAILURE; 355 356 dfs->dfs_cac_timer_running = val; 357 358 return QDF_STATUS_SUCCESS; 359 } 360 qdf_export_symbol(utils_dfs_set_cac_timer_running); 361 362 QDF_STATUS utils_dfs_get_nol_chfreq_and_chwidth(struct wlan_objmgr_pdev *pdev, 363 void *nollist, 364 uint32_t *nol_chfreq, 365 uint32_t *nol_chwidth, 366 int index) 367 { 368 struct wlan_dfs *dfs; 369 370 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 371 if (!dfs) 372 return QDF_STATUS_E_FAILURE; 373 374 dfs_get_nol_chfreq_and_chwidth(nollist, nol_chfreq, nol_chwidth, index); 375 376 return QDF_STATUS_SUCCESS; 377 } 378 qdf_export_symbol(utils_dfs_get_nol_chfreq_and_chwidth); 379 380 QDF_STATUS utils_dfs_update_cur_chan_flags(struct wlan_objmgr_pdev *pdev, 381 uint64_t flags, 382 uint16_t flagext) 383 { 384 struct wlan_dfs *dfs; 385 386 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 387 if (!dfs) 388 return QDF_STATUS_E_FAILURE; 389 390 dfs_update_cur_chan_flags(dfs, flags, flagext); 391 392 return QDF_STATUS_SUCCESS; 393 } 394 395 static void utils_dfs_get_max_phy_mode(struct wlan_objmgr_pdev *pdev, 396 uint32_t *phy_mode) 397 { 398 return; 399 } 400 401 static void utils_dfs_get_max_sup_width(struct wlan_objmgr_pdev *pdev, 402 uint8_t *ch_width) 403 { 404 return; 405 } 406 407 /** 408 * utils_dfs_get_chan_list() - Get channel list from regdb based on current 409 * operating channel. 410 * @pdev: Pointer to DFS pdev object. 411 * @chan_list: Pointer to current channel list 412 * @num_chan: number of channels in the current channel list. 413 */ 414 #ifndef QCA_DFS_USE_POLICY_MANAGER 415 static void utils_dfs_get_chan_list(struct wlan_objmgr_pdev *pdev, 416 struct dfs_channel *chan_list, uint32_t *num_chan) 417 { 418 int i = 0, j = 0; 419 enum channel_state state; 420 struct regulatory_channel *cur_chan_list; 421 struct wlan_dfs *dfs; 422 423 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 424 if (!dfs) 425 return; 426 427 cur_chan_list = qdf_mem_malloc(NUM_CHANNELS * 428 sizeof(struct regulatory_channel)); 429 if (!cur_chan_list) { 430 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, "fail to alloc"); 431 *num_chan = 0; 432 return; 433 } 434 435 if (wlan_reg_get_current_chan_list( 436 pdev, cur_chan_list) != QDF_STATUS_SUCCESS) { 437 *num_chan = 0; 438 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, 439 "failed to get curr channel list"); 440 return; 441 } 442 443 for (i = 0; i < NUM_CHANNELS; i++) { 444 state = cur_chan_list[i].state; 445 if (state == CHANNEL_STATE_DFS || 446 state == CHANNEL_STATE_ENABLE) { 447 chan_list[j].dfs_ch_ieee = cur_chan_list[i].chan_num; 448 chan_list[j].dfs_ch_freq = cur_chan_list[i].center_freq; 449 if (state == CHANNEL_STATE_DFS) 450 chan_list[j].dfs_ch_flagext = 451 WLAN_CHAN_DFS; 452 j++; 453 } 454 } 455 *num_chan = j; 456 qdf_mem_free(cur_chan_list); 457 458 return; 459 } 460 461 /** 462 * utils_dfs_get_channel_list() - Get channel list from regdb component based 463 * on current channel list. 464 * @pdev: Pointer to pdev structure. 465 * @chan_list: Pointer to regdb channel list. 466 * @num_chan: number of channels. 467 * 468 * Get regdb channel list based on dfs current channel. 469 * ex: When AP is operating in 5GHz channel, filter 2.4GHz and 4.9GHZ channels 470 * so that the random channel function does not select either 2.4GHz or 4.9GHz 471 * channel. 472 */ 473 static void utils_dfs_get_channel_list(struct wlan_objmgr_pdev *pdev, 474 struct dfs_channel *chan_list, uint32_t *num_chan) 475 { 476 struct dfs_channel *tmp_chan_list = NULL; 477 struct wlan_dfs *dfs; 478 bool is_curchan_5g; 479 bool is_curchan_24g; 480 bool is_curchan_49g; 481 uint32_t chan_num; 482 uint32_t center_freq; 483 uint16_t flagext; 484 int i, j = 0; 485 486 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 487 if (!dfs) { 488 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); 489 return; 490 } 491 492 tmp_chan_list = qdf_mem_malloc(*num_chan * sizeof(*tmp_chan_list)); 493 if (!tmp_chan_list) { 494 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, "mem alloc failed"); 495 return; 496 } 497 498 utils_dfs_get_chan_list(pdev, tmp_chan_list, num_chan); 499 500 chan_num = dfs->dfs_curchan->dfs_ch_ieee; 501 center_freq = dfs->dfs_curchan->dfs_ch_freq; 502 is_curchan_5g = WLAN_REG_IS_5GHZ_CH(chan_num); 503 is_curchan_24g = WLAN_REG_IS_24GHZ_CH(chan_num); 504 is_curchan_49g = WLAN_REG_IS_49GHZ_FREQ(center_freq); 505 506 for (i = 0; i < *num_chan; i++) { 507 chan_num = tmp_chan_list[i].dfs_ch_ieee; 508 center_freq = tmp_chan_list[i].dfs_ch_freq; 509 flagext = tmp_chan_list[i].dfs_ch_flagext; 510 511 if ((is_curchan_5g) && WLAN_REG_IS_5GHZ_CH(chan_num)) { 512 chan_list[j].dfs_ch_ieee = chan_num; 513 chan_list[j].dfs_ch_freq = center_freq; 514 chan_list[j].dfs_ch_flagext = flagext; 515 j++; 516 } else if ((is_curchan_24g) && 517 WLAN_REG_IS_24GHZ_CH(chan_num)) { 518 chan_list[j].dfs_ch_ieee = chan_num; 519 chan_list[j].dfs_ch_freq = center_freq; 520 j++; 521 } else if ((is_curchan_49g) && 522 WLAN_REG_IS_49GHZ_FREQ(center_freq)) { 523 chan_list[j].dfs_ch_ieee = chan_num; 524 chan_list[j].dfs_ch_freq = center_freq; 525 j++; 526 } 527 } 528 529 *num_chan = j; 530 531 qdf_mem_free(tmp_chan_list); 532 } 533 534 #else 535 536 static void utils_dfs_get_chan_list(struct wlan_objmgr_pdev *pdev, 537 struct dfs_channel *chan_list, uint32_t *num_chan) 538 { 539 uint8_t pcl_ch[NUM_CHANNELS] = {0}; 540 uint8_t weight_list[NUM_CHANNELS] = {0}; 541 uint32_t len; 542 uint32_t weight_len; 543 int i; 544 struct wlan_objmgr_psoc *psoc; 545 uint32_t conn_count = 0; 546 547 psoc = wlan_pdev_get_psoc(pdev); 548 if (!psoc) { 549 *num_chan = 0; 550 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "null psoc"); 551 return; 552 } 553 554 len = QDF_ARRAY_SIZE(pcl_ch); 555 weight_len = QDF_ARRAY_SIZE(weight_list); 556 conn_count = policy_mgr_mode_specific_connection_count( 557 psoc, PM_SAP_MODE, NULL); 558 if (0 == conn_count) 559 policy_mgr_get_pcl(psoc, PM_SAP_MODE, pcl_ch, 560 &len, weight_list, weight_len); 561 else 562 policy_mgr_get_pcl_for_existing_conn(psoc, PM_SAP_MODE, pcl_ch, 563 &len, weight_list, weight_len, true); 564 565 if (*num_chan < len) { 566 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 567 "Invalid len src=%d, dst=%d", 568 *num_chan, len); 569 *num_chan = 0; 570 return; 571 } 572 573 for (i = 0; i < len; i++) { 574 chan_list[i].dfs_ch_ieee = pcl_ch[i]; 575 chan_list[i].dfs_ch_freq = 576 wlan_reg_chan_to_freq(pdev, pcl_ch[i]); 577 } 578 *num_chan = i; 579 dfs_info(NULL, WLAN_DEBUG_DFS_ALWAYS, "num channels %d", i); 580 } 581 582 /** 583 * utils_dfs_get_channel_list() - Wrapper function to get channel list from 584 * regdb component. 585 * @pdev: Pointer to pdev structure. 586 * @chan_list: Pointer to regdb channel list. 587 * @num_chan: number of channels. 588 */ 589 static void utils_dfs_get_channel_list(struct wlan_objmgr_pdev *pdev, 590 struct dfs_channel *chan_list, uint32_t *num_chan) 591 { 592 utils_dfs_get_chan_list(pdev, chan_list, num_chan); 593 } 594 #endif 595 596 QDF_STATUS utils_dfs_get_random_channel( 597 struct wlan_objmgr_pdev *pdev, 598 uint16_t flags, 599 struct ch_params *ch_params, 600 uint32_t *hw_mode, 601 uint8_t *target_chan, 602 struct dfs_acs_info *acs_info) 603 { 604 uint32_t dfs_reg; 605 uint32_t num_chan = NUM_CHANNELS; 606 struct wlan_dfs *dfs = NULL; 607 struct wlan_objmgr_psoc *psoc; 608 struct dfs_channel *chan_list = NULL; 609 struct dfs_channel cur_chan; 610 QDF_STATUS status = QDF_STATUS_E_FAILURE; 611 612 *target_chan = 0; 613 psoc = wlan_pdev_get_psoc(pdev); 614 if (!psoc) { 615 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null psoc"); 616 goto random_chan_error; 617 } 618 619 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 620 if (!dfs) { 621 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); 622 goto random_chan_error; 623 } 624 625 wlan_reg_get_dfs_region(pdev, &dfs_reg); 626 chan_list = qdf_mem_malloc(num_chan * sizeof(*chan_list)); 627 if (!chan_list) { 628 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, "mem alloc failed"); 629 goto random_chan_error; 630 } 631 632 utils_dfs_get_channel_list(pdev, chan_list, &num_chan); 633 if (!num_chan) { 634 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "zero channels"); 635 goto random_chan_error; 636 } 637 638 cur_chan.dfs_ch_vhtop_ch_freq_seg1 = ch_params->center_freq_seg0; 639 cur_chan.dfs_ch_vhtop_ch_freq_seg2 = ch_params->center_freq_seg1; 640 641 if (!ch_params->ch_width) 642 utils_dfs_get_max_sup_width(pdev, 643 (uint8_t *)&ch_params->ch_width); 644 645 *target_chan = dfs_prepare_random_channel(dfs, chan_list, 646 num_chan, flags, (uint8_t *)&ch_params->ch_width, 647 &cur_chan, (uint8_t)dfs_reg, acs_info); 648 649 ch_params->center_freq_seg0 = cur_chan.dfs_ch_vhtop_ch_freq_seg1; 650 ch_params->center_freq_seg1 = cur_chan.dfs_ch_vhtop_ch_freq_seg2; 651 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 652 "input width=%d", ch_params->ch_width); 653 654 if (*target_chan) { 655 wlan_reg_set_channel_params(pdev, 656 *target_chan, 0, ch_params); 657 utils_dfs_get_max_phy_mode(pdev, hw_mode); 658 status = QDF_STATUS_SUCCESS; 659 } 660 661 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 662 "ch=%d, seg0=%d, seg1=%d, width=%d", 663 *target_chan, ch_params->center_freq_seg0, 664 ch_params->center_freq_seg1, ch_params->ch_width); 665 666 random_chan_error: 667 qdf_mem_free(chan_list); 668 669 return status; 670 } 671 qdf_export_symbol(utils_dfs_get_random_channel); 672 673 #ifdef QCA_DFS_NOL_PLATFORM_DRV_SUPPORT 674 void utils_dfs_init_nol(struct wlan_objmgr_pdev *pdev) 675 { 676 struct wlan_dfs *dfs; 677 struct wlan_objmgr_psoc *psoc; 678 qdf_device_t qdf_dev; 679 struct dfs_nol_info dfs_nolinfo; 680 int len; 681 682 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 683 psoc = wlan_pdev_get_psoc(pdev); 684 if (!dfs || !psoc) { 685 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, 686 "dfs %pK, psoc %pK", dfs, psoc); 687 return; 688 } 689 690 qdf_dev = psoc->soc_objmgr.qdf_dev; 691 if (!qdf_dev->dev) { 692 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null device"); 693 return; 694 } 695 696 qdf_mem_zero(&dfs_nolinfo, sizeof(dfs_nolinfo)); 697 len = pld_wlan_get_dfs_nol(qdf_dev->dev, (void *)&dfs_nolinfo, 698 (uint16_t)sizeof(dfs_nolinfo)); 699 if (len > 0) { 700 dfs_set_nol(dfs, dfs_nolinfo.dfs_nol, dfs_nolinfo.num_chans); 701 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "nol channels in pld"); 702 DFS_PRINT_NOL_LOCKED(dfs); 703 } else { 704 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "no nol in pld"); 705 } 706 } 707 #endif 708 qdf_export_symbol(utils_dfs_init_nol); 709 710 #ifndef QCA_DFS_NOL_PLATFORM_DRV_SUPPORT 711 void utils_dfs_save_nol(struct wlan_objmgr_pdev *pdev) 712 { 713 } 714 #else 715 void utils_dfs_save_nol(struct wlan_objmgr_pdev *pdev) 716 { 717 struct dfs_nol_info dfs_nolinfo; 718 struct wlan_dfs *dfs = NULL; 719 struct wlan_objmgr_psoc *psoc; 720 qdf_device_t qdf_dev; 721 int num_chans = 0; 722 723 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 724 if (!dfs) { 725 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); 726 return; 727 } 728 729 psoc = wlan_pdev_get_psoc(pdev); 730 if (!psoc) { 731 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null psoc"); 732 return; 733 } 734 735 qdf_dev = psoc->soc_objmgr.qdf_dev; 736 if (!qdf_dev->dev) { 737 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null device"); 738 return; 739 } 740 741 qdf_mem_zero(&dfs_nolinfo, sizeof(dfs_nolinfo)); 742 DFS_GET_NOL_LOCKED(dfs, dfs_nolinfo.dfs_nol, &num_chans); 743 if (num_chans > 0) { 744 745 if (num_chans > DFS_MAX_NOL_CHANNEL) 746 dfs_nolinfo.num_chans = DFS_MAX_NOL_CHANNEL; 747 else 748 dfs_nolinfo.num_chans = num_chans; 749 750 pld_wlan_set_dfs_nol(qdf_dev->dev, (void *)&dfs_nolinfo, 751 (uint16_t)sizeof(dfs_nolinfo)); 752 } 753 } 754 #endif 755 qdf_export_symbol(utils_dfs_save_nol); 756 757 void utils_dfs_print_nol_channels(struct wlan_objmgr_pdev *pdev) 758 { 759 struct wlan_dfs *dfs = NULL; 760 761 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 762 if (!dfs) { 763 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); 764 return; 765 } 766 767 DFS_PRINT_NOL_LOCKED(dfs); 768 } 769 qdf_export_symbol(utils_dfs_print_nol_channels); 770 771 void utils_dfs_clear_nol_channels(struct wlan_objmgr_pdev *pdev) 772 { 773 struct wlan_dfs *dfs = NULL; 774 775 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 776 if (!dfs) { 777 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); 778 return; 779 } 780 781 /* First print list */ 782 DFS_PRINT_NOL_LOCKED(dfs); 783 784 /* clear local cache first */ 785 dfs_nol_timer_cleanup(dfs); 786 dfs_nol_update(dfs); 787 788 /* 789 * update platform driver nol list with local cache which is zero, 790 * cleared in above step, so this will clear list in platform driver. 791 */ 792 utils_dfs_save_nol(pdev); 793 } 794 qdf_export_symbol(utils_dfs_clear_nol_channels); 795 796 void utils_dfs_reg_update_nol_ch(struct wlan_objmgr_pdev *pdev, 797 uint8_t *ch_list, 798 uint8_t num_ch, 799 bool nol_ch) 800 { 801 /* TODO : Need locking?*/ 802 wlan_reg_update_nol_ch(pdev, ch_list, num_ch, nol_ch); 803 } 804 qdf_export_symbol(utils_dfs_reg_update_nol_ch); 805 806 uint8_t utils_dfs_freq_to_chan(uint32_t freq) 807 { 808 uint8_t chan; 809 810 if (freq == 0) 811 return 0; 812 813 if (freq > DFS_24_GHZ_BASE_FREQ && freq < DFS_CHAN_14_FREQ) 814 chan = ((freq - DFS_24_GHZ_BASE_FREQ) / DFS_CHAN_SPACING_5MHZ); 815 else if (freq == DFS_CHAN_14_FREQ) 816 chan = DFS_24_GHZ_CHANNEL_14; 817 else if ((freq > DFS_24_GHZ_BASE_FREQ) && (freq < DFS_5_GHZ_BASE_FREQ)) 818 chan = (((freq - DFS_CHAN_15_FREQ) / DFS_CHAN_SPACING_20MHZ) + 819 DFS_24_GHZ_CHANNEL_15); 820 else 821 chan = (freq - DFS_5_GHZ_BASE_FREQ) / DFS_CHAN_SPACING_5MHZ; 822 823 return chan; 824 } 825 qdf_export_symbol(utils_dfs_freq_to_chan); 826 827 uint32_t utils_dfs_chan_to_freq(uint8_t chan) 828 { 829 if (chan == 0) 830 return 0; 831 832 if (chan < DFS_24_GHZ_CHANNEL_14) 833 return DFS_24_GHZ_BASE_FREQ + (chan * DFS_CHAN_SPACING_5MHZ); 834 else if (chan == DFS_24_GHZ_CHANNEL_14) 835 return DFS_CHAN_14_FREQ; 836 else if (chan < DFS_24_GHZ_CHANNEL_27) 837 return DFS_CHAN_15_FREQ + ((chan - DFS_24_GHZ_CHANNEL_15) * 838 DFS_CHAN_SPACING_20MHZ); 839 else if (chan == DFS_5_GHZ_CHANNEL_170) 840 return DFS_CHAN_170_FREQ; 841 else 842 return DFS_5_GHZ_BASE_FREQ + (chan * DFS_CHAN_SPACING_5MHZ); 843 } 844 qdf_export_symbol(utils_dfs_chan_to_freq); 845 846 #ifdef QCA_MCL_DFS_SUPPORT 847 QDF_STATUS utils_dfs_mark_leaking_ch(struct wlan_objmgr_pdev *pdev, 848 enum phy_ch_width ch_width, 849 uint8_t temp_ch_lst_sz, 850 uint8_t *temp_ch_lst) 851 { 852 struct wlan_dfs *dfs = NULL; 853 854 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 855 if (!dfs) { 856 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); 857 return QDF_STATUS_E_FAILURE; 858 } 859 860 return dfs_mark_leaking_ch(dfs, ch_width, temp_ch_lst_sz, temp_ch_lst); 861 } 862 qdf_export_symbol(utils_dfs_mark_leaking_ch); 863 #endif 864 865 int utils_get_dfsdomain(struct wlan_objmgr_pdev *pdev) 866 { 867 enum dfs_reg dfsdomain; 868 869 wlan_reg_get_dfs_region(pdev, &dfsdomain); 870 871 return dfsdomain; 872 } 873 874 uint16_t utils_dfs_get_cur_rd(struct wlan_objmgr_pdev *pdev) 875 { 876 struct cur_regdmn_info cur_regdmn; 877 878 wlan_reg_get_curr_regdomain(pdev, &cur_regdmn); 879 880 return cur_regdmn.regdmn_pair_id; 881 } 882 883 #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST) 884 QDF_STATUS utils_dfs_is_spoof_check_failed(struct wlan_objmgr_pdev *pdev, 885 bool *is_spoof_check_failed) 886 { 887 struct wlan_dfs *dfs; 888 889 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 890 if (!dfs) { 891 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); 892 return QDF_STATUS_E_FAILURE; 893 } 894 895 *is_spoof_check_failed = dfs->dfs_spoof_check_failed; 896 897 return QDF_STATUS_SUCCESS; 898 } 899 900 qdf_export_symbol(utils_dfs_is_spoof_check_failed); 901 #endif 902