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 "wlan_dfs_mlme_api.h" 26 #include "../../core/src/dfs.h" 27 #include "../../core/src/dfs_zero_cac.h" 28 #include "../../core/src/dfs_etsi_precac.h" 29 #include <wlan_reg_services_api.h> 30 #include "../../core/src/dfs_random_chan_sel.h" 31 #ifdef QCA_DFS_USE_POLICY_MANAGER 32 #include "wlan_policy_mgr_api.h" 33 #endif 34 #ifdef QCA_DFS_NOL_PLATFORM_DRV_SUPPORT 35 #include <pld_common.h> 36 #endif 37 #include <qdf_module.h> 38 39 struct dfs_nol_info { 40 uint16_t num_chans; 41 struct dfsreq_nolelem dfs_nol[DFS_MAX_NOL_CHANNEL]; 42 }; 43 44 QDF_STATUS utils_dfs_reset(struct wlan_objmgr_pdev *pdev) 45 { 46 struct wlan_dfs *dfs; 47 48 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 49 if (!dfs) 50 return QDF_STATUS_E_FAILURE; 51 52 dfs_reset(dfs); 53 dfs_nol_update(dfs); 54 dfs_reset_precaclists(dfs); 55 dfs_reset_etsiprecaclists(dfs); 56 57 return QDF_STATUS_SUCCESS; 58 } 59 60 bool utils_dfs_freq_is_in_nol(struct wlan_objmgr_pdev *pdev, uint32_t freq) 61 { 62 struct wlan_dfs *dfs; 63 64 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 65 if (!dfs) 66 return false; 67 68 return dfs_freq_is_in_nol(dfs, freq); 69 } 70 71 QDF_STATUS utils_dfs_cac_valid_reset(struct wlan_objmgr_pdev *pdev, 72 uint8_t prevchan_ieee, 73 uint32_t prevchan_flags) 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_cac_valid_reset(dfs, prevchan_ieee, prevchan_flags); 82 83 return QDF_STATUS_SUCCESS; 84 } 85 qdf_export_symbol(utils_dfs_cac_valid_reset); 86 87 QDF_STATUS utils_dfs_reset_precaclists(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_reset_precaclists(dfs); 96 97 return QDF_STATUS_SUCCESS; 98 } 99 qdf_export_symbol(utils_dfs_reset_precaclists); 100 101 #ifdef QCA_SUPPORT_ETSI_PRECAC_DFS 102 QDF_STATUS utils_dfs_reset_etsi_precaclists(struct wlan_objmgr_pdev *pdev) 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 dfs_reset_etsiprecaclists(dfs); 111 112 return QDF_STATUS_SUCCESS; 113 } 114 115 qdf_export_symbol(utils_dfs_reset_etsi_precaclists); 116 #endif 117 118 QDF_STATUS utils_dfs_cancel_precac_timer(struct wlan_objmgr_pdev *pdev) 119 { 120 struct wlan_dfs *dfs; 121 122 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 123 if (!dfs) 124 return QDF_STATUS_E_FAILURE; 125 126 dfs_cancel_precac_timer(dfs); 127 128 return QDF_STATUS_SUCCESS; 129 } 130 qdf_export_symbol(utils_dfs_cancel_precac_timer); 131 132 QDF_STATUS utils_dfs_start_precac_timer(struct wlan_objmgr_pdev *pdev) 133 { 134 struct wlan_dfs *dfs; 135 136 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 137 if (!dfs) { 138 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "NULL dfs"); 139 return QDF_STATUS_E_FAILURE; 140 } 141 dfs_start_precac_timer(dfs, dfs->dfs_precac_secondary_freq); 142 return QDF_STATUS_SUCCESS; 143 } 144 145 #ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT 146 QDF_STATUS utils_dfs_precac_decide_pref_chan(struct wlan_objmgr_pdev *pdev, 147 uint8_t *ch_ieee) 148 { 149 struct wlan_dfs *dfs; 150 151 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 152 if (!dfs) { 153 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "NULL dfs"); 154 return QDF_STATUS_E_FAILURE; 155 } 156 dfs_decide_precac_preferred_chan(dfs, ch_ieee); 157 158 return QDF_STATUS_SUCCESS; 159 } 160 #endif 161 162 QDF_STATUS utils_dfs_is_precac_done(struct wlan_objmgr_pdev *pdev, 163 bool *is_precac_done) 164 { 165 struct wlan_dfs *dfs; 166 167 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 168 if (!dfs) 169 return QDF_STATUS_E_FAILURE; 170 171 *is_precac_done = dfs_is_precac_done(dfs, dfs->dfs_curchan); 172 173 return QDF_STATUS_SUCCESS; 174 } 175 qdf_export_symbol(utils_dfs_is_precac_done); 176 177 #ifdef QCA_SUPPORT_ETSI_PRECAC_DFS 178 QDF_STATUS utils_dfs_is_etsi_precac_done(struct wlan_objmgr_pdev *pdev, 179 bool *is_etsi_precac_done) 180 { 181 struct wlan_dfs *dfs; 182 183 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 184 if (!dfs) 185 return QDF_STATUS_E_FAILURE; 186 187 *is_etsi_precac_done = dfs_is_etsi_precac_done(dfs); 188 189 return QDF_STATUS_SUCCESS; 190 } 191 192 qdf_export_symbol(utils_dfs_is_etsi_precac_done); 193 #endif 194 195 QDF_STATUS utils_dfs_cancel_cac_timer(struct wlan_objmgr_pdev *pdev) 196 { 197 struct wlan_dfs *dfs; 198 199 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 200 if (!dfs) 201 return QDF_STATUS_E_FAILURE; 202 203 dfs_cancel_cac_timer(dfs); 204 205 return QDF_STATUS_SUCCESS; 206 } 207 qdf_export_symbol(utils_dfs_cancel_cac_timer); 208 209 QDF_STATUS utils_dfs_start_cac_timer(struct wlan_objmgr_pdev *pdev) 210 { 211 struct wlan_dfs *dfs; 212 213 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 214 if (!dfs) 215 return QDF_STATUS_E_FAILURE; 216 217 dfs_start_cac_timer(dfs); 218 219 return QDF_STATUS_SUCCESS; 220 } 221 qdf_export_symbol(utils_dfs_start_cac_timer); 222 223 QDF_STATUS utils_dfs_cac_stop(struct wlan_objmgr_pdev *pdev) 224 { 225 struct wlan_dfs *dfs; 226 227 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 228 if (!dfs) 229 return QDF_STATUS_E_FAILURE; 230 231 dfs_cac_stop(dfs); 232 return QDF_STATUS_SUCCESS; 233 } 234 qdf_export_symbol(utils_dfs_cac_stop); 235 236 QDF_STATUS utils_dfs_stacac_stop(struct wlan_objmgr_pdev *pdev) 237 { 238 struct wlan_dfs *dfs; 239 240 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 241 if (!dfs) 242 return QDF_STATUS_E_FAILURE; 243 244 dfs_stacac_stop(dfs); 245 246 return QDF_STATUS_SUCCESS; 247 } 248 qdf_export_symbol(utils_dfs_stacac_stop); 249 250 bool utils_dfs_is_curchan_subset_of_cac_started_chan( 251 struct wlan_objmgr_pdev *pdev) 252 { 253 struct wlan_dfs *dfs; 254 255 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 256 if (!dfs) 257 return false; 258 259 return dfs_is_curchan_subset_of_cac_started_chan(dfs); 260 } 261 262 bool utils_dfs_is_cac_aborted(struct wlan_objmgr_pdev *pdev) 263 { 264 struct wlan_dfs *dfs; 265 266 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 267 if (!dfs) 268 return false; 269 270 return dfs->dfs_cac_aborted; 271 } 272 273 void utils_dfs_clear_cac_started_chan(struct wlan_objmgr_pdev *pdev) 274 { 275 struct wlan_dfs *dfs; 276 277 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 278 if (!dfs) 279 return; 280 281 dfs_clear_cac_started_chan(dfs); 282 } 283 284 QDF_STATUS utils_dfs_get_usenol(struct wlan_objmgr_pdev *pdev, uint16_t *usenol) 285 { 286 struct wlan_dfs *dfs; 287 288 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 289 if (!dfs) 290 return QDF_STATUS_E_FAILURE; 291 292 *usenol = dfs_get_use_nol(dfs); 293 294 return QDF_STATUS_SUCCESS; 295 } 296 qdf_export_symbol(utils_dfs_get_usenol); 297 298 QDF_STATUS utils_dfs_radar_disable(struct wlan_objmgr_pdev *pdev) 299 { 300 struct wlan_dfs *dfs; 301 302 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 303 if (!dfs) 304 return QDF_STATUS_E_FAILURE; 305 306 dfs_radar_disable(dfs); 307 308 return QDF_STATUS_SUCCESS; 309 } 310 qdf_export_symbol(utils_dfs_radar_disable); 311 312 QDF_STATUS utils_dfs_set_update_nol_flag(struct wlan_objmgr_pdev *pdev, 313 bool val) 314 { 315 struct wlan_dfs *dfs; 316 317 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 318 if (!dfs) 319 return QDF_STATUS_E_FAILURE; 320 321 dfs_set_update_nol_flag(dfs, val); 322 323 return QDF_STATUS_SUCCESS; 324 } 325 qdf_export_symbol(utils_dfs_set_update_nol_flag); 326 327 QDF_STATUS utils_dfs_get_update_nol_flag(struct wlan_objmgr_pdev *pdev, 328 bool *nol_flag) 329 { 330 struct wlan_dfs *dfs; 331 332 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 333 if (!dfs) 334 return QDF_STATUS_E_FAILURE; 335 336 *nol_flag = dfs_get_update_nol_flag(dfs); 337 338 return QDF_STATUS_SUCCESS; 339 } 340 qdf_export_symbol(utils_dfs_get_update_nol_flag); 341 342 QDF_STATUS utils_dfs_get_dfs_use_nol(struct wlan_objmgr_pdev *pdev, 343 int *dfs_use_nol) 344 { 345 struct wlan_dfs *dfs; 346 347 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 348 if (!dfs) 349 return QDF_STATUS_E_FAILURE; 350 351 *dfs_use_nol = dfs_get_use_nol(dfs); 352 353 return QDF_STATUS_SUCCESS; 354 } 355 qdf_export_symbol(utils_dfs_get_dfs_use_nol); 356 357 QDF_STATUS utils_dfs_get_nol_timeout(struct wlan_objmgr_pdev *pdev, 358 int *dfs_nol_timeout) 359 { 360 struct wlan_dfs *dfs; 361 362 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 363 if (!dfs) 364 return QDF_STATUS_E_FAILURE; 365 366 *dfs_nol_timeout = dfs_get_nol_timeout(dfs); 367 368 return QDF_STATUS_SUCCESS; 369 } 370 qdf_export_symbol(utils_dfs_get_nol_timeout); 371 372 QDF_STATUS utils_dfs_nol_addchan(struct wlan_objmgr_pdev *pdev, 373 uint16_t freq, 374 uint32_t dfs_nol_timeout) 375 { 376 struct wlan_dfs *dfs; 377 378 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 379 if (!dfs) 380 return QDF_STATUS_E_FAILURE; 381 382 DFS_NOL_ADD_CHAN_LOCKED(dfs, freq, dfs_nol_timeout); 383 384 return QDF_STATUS_SUCCESS; 385 } 386 qdf_export_symbol(utils_dfs_nol_addchan); 387 388 QDF_STATUS utils_dfs_nol_update(struct wlan_objmgr_pdev *pdev) 389 { 390 struct wlan_dfs *dfs; 391 392 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 393 if (!dfs) 394 return QDF_STATUS_E_FAILURE; 395 396 dfs_nol_update(dfs); 397 398 return QDF_STATUS_SUCCESS; 399 } 400 qdf_export_symbol(utils_dfs_nol_update); 401 402 QDF_STATUS utils_dfs_second_segment_radar_disable(struct wlan_objmgr_pdev *pdev) 403 { 404 struct wlan_dfs *dfs; 405 406 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 407 if (!dfs) 408 return QDF_STATUS_E_FAILURE; 409 410 dfs_second_segment_radar_disable(dfs); 411 412 return QDF_STATUS_SUCCESS; 413 } 414 415 QDF_STATUS utils_dfs_is_ignore_dfs(struct wlan_objmgr_pdev *pdev, 416 bool *ignore_dfs) 417 { 418 struct wlan_dfs *dfs; 419 420 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 421 if (!dfs) 422 return QDF_STATUS_E_FAILURE; 423 424 *ignore_dfs = dfs->dfs_ignore_dfs; 425 426 return QDF_STATUS_SUCCESS; 427 } 428 qdf_export_symbol(utils_dfs_is_ignore_dfs); 429 430 QDF_STATUS utils_dfs_is_cac_valid(struct wlan_objmgr_pdev *pdev, 431 bool *is_cac_valid) 432 { 433 struct wlan_dfs *dfs; 434 435 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 436 if (!dfs) 437 return QDF_STATUS_E_FAILURE; 438 439 *is_cac_valid = dfs->dfs_cac_valid; 440 441 return QDF_STATUS_SUCCESS; 442 } 443 qdf_export_symbol(utils_dfs_is_cac_valid); 444 445 QDF_STATUS utils_dfs_is_ignore_cac(struct wlan_objmgr_pdev *pdev, 446 bool *ignore_cac) 447 { 448 struct wlan_dfs *dfs; 449 450 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 451 if (!dfs) 452 return QDF_STATUS_E_FAILURE; 453 454 *ignore_cac = dfs->dfs_ignore_cac; 455 456 /* 457 * This is needed as, if after channel bandwidth reduction, channel 458 * change occurs using dothchanswitch or chan commands, resetting. 459 * dfs->dfs_ignore_cac will make sure we not skip CAC on the new channel 460 */ 461 462 if (dfs->dfs_bw_reduced) 463 dfs->dfs_ignore_cac = 0; 464 465 return QDF_STATUS_SUCCESS; 466 } 467 qdf_export_symbol(utils_dfs_is_ignore_cac); 468 469 QDF_STATUS utils_dfs_set_cac_timer_running(struct wlan_objmgr_pdev *pdev, 470 int val) 471 { 472 struct wlan_dfs *dfs; 473 474 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 475 if (!dfs) 476 return QDF_STATUS_E_FAILURE; 477 478 dfs->dfs_cac_timer_running = val; 479 480 return QDF_STATUS_SUCCESS; 481 } 482 qdf_export_symbol(utils_dfs_set_cac_timer_running); 483 484 QDF_STATUS utils_dfs_get_nol_chfreq_and_chwidth(struct wlan_objmgr_pdev *pdev, 485 void *nollist, 486 uint32_t *nol_chfreq, 487 uint32_t *nol_chwidth, 488 int index) 489 { 490 struct wlan_dfs *dfs; 491 492 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 493 if (!dfs) 494 return QDF_STATUS_E_FAILURE; 495 496 dfs_get_nol_chfreq_and_chwidth(nollist, nol_chfreq, nol_chwidth, index); 497 498 return QDF_STATUS_SUCCESS; 499 } 500 qdf_export_symbol(utils_dfs_get_nol_chfreq_and_chwidth); 501 502 QDF_STATUS utils_dfs_update_cur_chan_flags(struct wlan_objmgr_pdev *pdev, 503 uint64_t flags, 504 uint16_t flagext) 505 { 506 struct wlan_dfs *dfs; 507 508 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 509 if (!dfs) 510 return QDF_STATUS_E_FAILURE; 511 512 dfs_update_cur_chan_flags(dfs, flags, flagext); 513 514 return QDF_STATUS_SUCCESS; 515 } 516 517 static void utils_dfs_get_max_phy_mode(struct wlan_objmgr_pdev *pdev, 518 uint32_t *phy_mode) 519 { 520 return; 521 } 522 523 static void utils_dfs_get_max_sup_width(struct wlan_objmgr_pdev *pdev, 524 uint8_t *ch_width) 525 { 526 return; 527 } 528 529 /** 530 * utils_dfs_get_chan_list() - Get channel list from regdb based on current 531 * operating channel. 532 * @pdev: Pointer to DFS pdev object. 533 * @chan_list: Pointer to current channel list 534 * @num_chan: number of channels in the current channel list. 535 */ 536 #ifndef QCA_DFS_USE_POLICY_MANAGER 537 static void utils_dfs_get_chan_list(struct wlan_objmgr_pdev *pdev, 538 struct dfs_channel *chan_list, uint32_t *num_chan) 539 { 540 int i = 0, j = 0; 541 enum channel_state state; 542 struct regulatory_channel *cur_chan_list; 543 struct wlan_dfs *dfs; 544 545 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 546 if (!dfs) 547 return; 548 549 cur_chan_list = qdf_mem_malloc(NUM_CHANNELS * 550 sizeof(struct regulatory_channel)); 551 if (!cur_chan_list) { 552 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, "fail to alloc"); 553 *num_chan = 0; 554 return; 555 } 556 557 if (wlan_reg_get_current_chan_list( 558 pdev, cur_chan_list) != QDF_STATUS_SUCCESS) { 559 *num_chan = 0; 560 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, 561 "failed to get curr channel list"); 562 return; 563 } 564 565 for (i = 0; i < NUM_CHANNELS; i++) { 566 state = cur_chan_list[i].state; 567 if (state == CHANNEL_STATE_DFS || 568 state == CHANNEL_STATE_ENABLE) { 569 chan_list[j].dfs_ch_ieee = cur_chan_list[i].chan_num; 570 chan_list[j].dfs_ch_freq = cur_chan_list[i].center_freq; 571 if (state == CHANNEL_STATE_DFS) 572 chan_list[j].dfs_ch_flagext = 573 WLAN_CHAN_DFS; 574 j++; 575 } 576 } 577 *num_chan = j; 578 qdf_mem_free(cur_chan_list); 579 580 return; 581 } 582 583 /** 584 * utils_dfs_get_channel_list() - Get channel list from regdb component based 585 * on current channel list. 586 * @pdev: Pointer to pdev structure. 587 * @chan_list: Pointer to regdb channel list. 588 * @num_chan: number of channels. 589 * 590 * Get regdb channel list based on dfs current channel. 591 * ex: When AP is operating in 5GHz channel, filter 2.4GHz and 4.9GHZ channels 592 * so that the random channel function does not select either 2.4GHz or 4.9GHz 593 * channel. 594 */ 595 static void utils_dfs_get_channel_list(struct wlan_objmgr_pdev *pdev, 596 struct dfs_channel *chan_list, uint32_t *num_chan) 597 { 598 struct dfs_channel *tmp_chan_list = NULL; 599 struct wlan_dfs *dfs; 600 bool is_curchan_5g; 601 bool is_curchan_24g; 602 bool is_curchan_49g; 603 uint32_t chan_num; 604 uint32_t center_freq; 605 uint16_t flagext; 606 int i, j = 0; 607 608 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 609 if (!dfs) { 610 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); 611 return; 612 } 613 614 tmp_chan_list = qdf_mem_malloc(*num_chan * sizeof(*tmp_chan_list)); 615 if (!tmp_chan_list) { 616 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, "mem alloc failed"); 617 return; 618 } 619 620 utils_dfs_get_chan_list(pdev, tmp_chan_list, num_chan); 621 622 chan_num = dfs->dfs_curchan->dfs_ch_ieee; 623 center_freq = dfs->dfs_curchan->dfs_ch_freq; 624 is_curchan_5g = WLAN_REG_IS_5GHZ_CH(chan_num); 625 is_curchan_24g = WLAN_REG_IS_24GHZ_CH(chan_num); 626 is_curchan_49g = WLAN_REG_IS_49GHZ_FREQ(center_freq); 627 628 for (i = 0; i < *num_chan; i++) { 629 chan_num = tmp_chan_list[i].dfs_ch_ieee; 630 center_freq = tmp_chan_list[i].dfs_ch_freq; 631 flagext = tmp_chan_list[i].dfs_ch_flagext; 632 633 if (!dfs_mlme_check_allowed_prim_chanlist(pdev, chan_num)) 634 continue; 635 636 if ((is_curchan_5g) && WLAN_REG_IS_5GHZ_CH(chan_num)) { 637 chan_list[j].dfs_ch_ieee = chan_num; 638 chan_list[j].dfs_ch_freq = center_freq; 639 chan_list[j].dfs_ch_flagext = flagext; 640 j++; 641 } else if ((is_curchan_24g) && 642 WLAN_REG_IS_24GHZ_CH(chan_num)) { 643 chan_list[j].dfs_ch_ieee = chan_num; 644 chan_list[j].dfs_ch_freq = center_freq; 645 j++; 646 } else if ((is_curchan_49g) && 647 WLAN_REG_IS_49GHZ_FREQ(center_freq)) { 648 chan_list[j].dfs_ch_ieee = chan_num; 649 chan_list[j].dfs_ch_freq = center_freq; 650 j++; 651 } 652 } 653 654 *num_chan = j; 655 656 qdf_mem_free(tmp_chan_list); 657 } 658 659 #else 660 661 static void utils_dfs_get_chan_list(struct wlan_objmgr_pdev *pdev, 662 struct dfs_channel *chan_list, uint32_t *num_chan) 663 { 664 uint8_t pcl_ch[QDF_MAX_NUM_CHAN] = {0}; 665 uint8_t weight_list[QDF_MAX_NUM_CHAN] = {0}; 666 uint32_t len; 667 uint32_t weight_len; 668 int i; 669 struct wlan_objmgr_psoc *psoc; 670 uint32_t conn_count = 0; 671 672 psoc = wlan_pdev_get_psoc(pdev); 673 if (!psoc) { 674 *num_chan = 0; 675 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "null psoc"); 676 return; 677 } 678 679 len = QDF_ARRAY_SIZE(pcl_ch); 680 weight_len = QDF_ARRAY_SIZE(weight_list); 681 conn_count = policy_mgr_mode_specific_connection_count( 682 psoc, PM_SAP_MODE, NULL); 683 if (0 == conn_count) 684 policy_mgr_get_pcl(psoc, PM_SAP_MODE, pcl_ch, 685 &len, weight_list, weight_len); 686 else 687 policy_mgr_get_pcl_for_existing_conn(psoc, PM_SAP_MODE, pcl_ch, 688 &len, weight_list, weight_len, true); 689 690 if (*num_chan < len) { 691 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 692 "Invalid len src=%d, dst=%d", 693 *num_chan, len); 694 *num_chan = 0; 695 return; 696 } 697 698 for (i = 0; i < len; i++) { 699 chan_list[i].dfs_ch_ieee = pcl_ch[i]; 700 chan_list[i].dfs_ch_freq = 701 wlan_reg_chan_to_freq(pdev, pcl_ch[i]); 702 } 703 *num_chan = i; 704 dfs_info(NULL, WLAN_DEBUG_DFS_ALWAYS, "num channels %d", i); 705 } 706 707 /** 708 * utils_dfs_get_channel_list() - Wrapper function to get channel list from 709 * regdb component. 710 * @pdev: Pointer to pdev structure. 711 * @chan_list: Pointer to regdb channel list. 712 * @num_chan: number of channels. 713 */ 714 static void utils_dfs_get_channel_list(struct wlan_objmgr_pdev *pdev, 715 struct dfs_channel *chan_list, uint32_t *num_chan) 716 { 717 utils_dfs_get_chan_list(pdev, chan_list, num_chan); 718 } 719 #endif 720 721 QDF_STATUS utils_dfs_get_random_channel( 722 struct wlan_objmgr_pdev *pdev, 723 uint16_t flags, 724 struct ch_params *ch_params, 725 uint32_t *hw_mode, 726 uint8_t *target_chan, 727 struct dfs_acs_info *acs_info) 728 { 729 uint32_t dfs_reg; 730 uint32_t num_chan = NUM_CHANNELS; 731 struct wlan_dfs *dfs = NULL; 732 struct wlan_objmgr_psoc *psoc; 733 struct dfs_channel *chan_list = NULL; 734 struct dfs_channel cur_chan; 735 QDF_STATUS status = QDF_STATUS_E_FAILURE; 736 737 *target_chan = 0; 738 psoc = wlan_pdev_get_psoc(pdev); 739 if (!psoc) { 740 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null psoc"); 741 goto random_chan_error; 742 } 743 744 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 745 if (!dfs) { 746 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); 747 goto random_chan_error; 748 } 749 750 wlan_reg_get_dfs_region(pdev, &dfs_reg); 751 chan_list = qdf_mem_malloc(num_chan * sizeof(*chan_list)); 752 if (!chan_list) { 753 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, "mem alloc failed"); 754 goto random_chan_error; 755 } 756 757 utils_dfs_get_channel_list(pdev, chan_list, &num_chan); 758 if (!num_chan) { 759 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "zero channels"); 760 goto random_chan_error; 761 } 762 763 cur_chan.dfs_ch_vhtop_ch_freq_seg1 = ch_params->center_freq_seg0; 764 cur_chan.dfs_ch_vhtop_ch_freq_seg2 = ch_params->center_freq_seg1; 765 766 if (!ch_params->ch_width) 767 utils_dfs_get_max_sup_width(pdev, 768 (uint8_t *)&ch_params->ch_width); 769 770 *target_chan = dfs_prepare_random_channel(dfs, chan_list, 771 num_chan, flags, (uint8_t *)&ch_params->ch_width, 772 &cur_chan, (uint8_t)dfs_reg, acs_info); 773 774 ch_params->center_freq_seg0 = cur_chan.dfs_ch_vhtop_ch_freq_seg1; 775 ch_params->center_freq_seg1 = cur_chan.dfs_ch_vhtop_ch_freq_seg2; 776 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 777 "input width=%d", ch_params->ch_width); 778 779 if (*target_chan) { 780 wlan_reg_set_channel_params(pdev, 781 *target_chan, 0, ch_params); 782 utils_dfs_get_max_phy_mode(pdev, hw_mode); 783 status = QDF_STATUS_SUCCESS; 784 } 785 786 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 787 "ch=%d, seg0=%d, seg1=%d, width=%d", 788 *target_chan, ch_params->center_freq_seg0, 789 ch_params->center_freq_seg1, ch_params->ch_width); 790 791 random_chan_error: 792 qdf_mem_free(chan_list); 793 794 return status; 795 } 796 qdf_export_symbol(utils_dfs_get_random_channel); 797 798 QDF_STATUS utils_dfs_bw_reduced_channel( 799 struct wlan_objmgr_pdev *pdev, 800 uint16_t flags, 801 struct ch_params *ch_params, 802 uint32_t *hw_mode, 803 uint8_t *target_chan) 804 { 805 struct wlan_dfs *dfs = NULL; 806 struct wlan_objmgr_psoc *psoc; 807 enum channel_state ch_state; 808 QDF_STATUS status = QDF_STATUS_E_FAILURE; 809 810 *target_chan = 0; 811 psoc = wlan_pdev_get_psoc(pdev); 812 if (!psoc) { 813 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null psoc"); 814 return status; 815 } 816 817 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 818 if (!dfs) { 819 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); 820 return status; 821 } 822 823 ch_state = reg_get_channel_state(pdev, dfs->dfs_curchan->dfs_ch_ieee); 824 825 if (ch_state == CHANNEL_STATE_DFS || 826 ch_state == CHANNEL_STATE_ENABLE) { 827 ch_params->center_freq_seg0 = 828 dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg1; 829 ch_params->center_freq_seg1 = 830 dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2; 831 dfs->dfs_bw_reduced = 1; 832 wlan_reg_set_channel_params(pdev, 833 dfs->dfs_curchan->dfs_ch_ieee, 834 0, ch_params); 835 836 *target_chan = dfs->dfs_curchan->dfs_ch_ieee; 837 utils_dfs_get_max_phy_mode(pdev, hw_mode); 838 839 return QDF_STATUS_SUCCESS; 840 } 841 842 return status; 843 } 844 845 #ifdef QCA_DFS_NOL_PLATFORM_DRV_SUPPORT 846 void utils_dfs_init_nol(struct wlan_objmgr_pdev *pdev) 847 { 848 struct wlan_dfs *dfs; 849 struct wlan_objmgr_psoc *psoc; 850 qdf_device_t qdf_dev; 851 struct dfs_nol_info dfs_nolinfo; 852 int len; 853 854 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 855 psoc = wlan_pdev_get_psoc(pdev); 856 if (!dfs || !psoc) { 857 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, 858 "dfs %pK, psoc %pK", dfs, psoc); 859 return; 860 } 861 862 qdf_dev = psoc->soc_objmgr.qdf_dev; 863 if (!qdf_dev->dev) { 864 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null device"); 865 return; 866 } 867 868 qdf_mem_zero(&dfs_nolinfo, sizeof(dfs_nolinfo)); 869 len = pld_wlan_get_dfs_nol(qdf_dev->dev, (void *)&dfs_nolinfo, 870 (uint16_t)sizeof(dfs_nolinfo)); 871 if (len > 0) { 872 dfs_set_nol(dfs, dfs_nolinfo.dfs_nol, dfs_nolinfo.num_chans); 873 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "nol channels in pld"); 874 DFS_PRINT_NOL_LOCKED(dfs); 875 } else { 876 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "no nol in pld"); 877 } 878 } 879 #endif 880 qdf_export_symbol(utils_dfs_init_nol); 881 882 #ifndef QCA_DFS_NOL_PLATFORM_DRV_SUPPORT 883 void utils_dfs_save_nol(struct wlan_objmgr_pdev *pdev) 884 { 885 } 886 #else 887 void utils_dfs_save_nol(struct wlan_objmgr_pdev *pdev) 888 { 889 struct dfs_nol_info dfs_nolinfo; 890 struct wlan_dfs *dfs = NULL; 891 struct wlan_objmgr_psoc *psoc; 892 qdf_device_t qdf_dev; 893 int num_chans = 0; 894 895 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 896 if (!dfs) { 897 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); 898 return; 899 } 900 901 psoc = wlan_pdev_get_psoc(pdev); 902 if (!psoc) { 903 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null psoc"); 904 return; 905 } 906 907 qdf_dev = psoc->soc_objmgr.qdf_dev; 908 if (!qdf_dev->dev) { 909 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null device"); 910 return; 911 } 912 913 qdf_mem_zero(&dfs_nolinfo, sizeof(dfs_nolinfo)); 914 DFS_GET_NOL_LOCKED(dfs, dfs_nolinfo.dfs_nol, &num_chans); 915 if (num_chans > 0) { 916 917 if (num_chans > DFS_MAX_NOL_CHANNEL) 918 dfs_nolinfo.num_chans = DFS_MAX_NOL_CHANNEL; 919 else 920 dfs_nolinfo.num_chans = num_chans; 921 922 pld_wlan_set_dfs_nol(qdf_dev->dev, (void *)&dfs_nolinfo, 923 (uint16_t)sizeof(dfs_nolinfo)); 924 } 925 } 926 #endif 927 qdf_export_symbol(utils_dfs_save_nol); 928 929 void utils_dfs_print_nol_channels(struct wlan_objmgr_pdev *pdev) 930 { 931 struct wlan_dfs *dfs = NULL; 932 933 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 934 if (!dfs) { 935 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); 936 return; 937 } 938 939 DFS_PRINT_NOL_LOCKED(dfs); 940 } 941 qdf_export_symbol(utils_dfs_print_nol_channels); 942 943 void utils_dfs_clear_nol_channels(struct wlan_objmgr_pdev *pdev) 944 { 945 struct wlan_dfs *dfs = NULL; 946 947 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 948 if (!dfs) { 949 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); 950 return; 951 } 952 953 /* First print list */ 954 DFS_PRINT_NOL_LOCKED(dfs); 955 956 /* clear local cache first */ 957 dfs_nol_timer_cleanup(dfs); 958 dfs_nol_update(dfs); 959 960 /* 961 * update platform driver nol list with local cache which is zero, 962 * cleared in above step, so this will clear list in platform driver. 963 */ 964 utils_dfs_save_nol(pdev); 965 } 966 qdf_export_symbol(utils_dfs_clear_nol_channels); 967 968 void utils_dfs_reg_update_nol_ch(struct wlan_objmgr_pdev *pdev, 969 uint8_t *ch_list, 970 uint8_t num_ch, 971 bool nol_ch) 972 { 973 /* TODO : Need locking?*/ 974 wlan_reg_update_nol_ch(pdev, ch_list, num_ch, nol_ch); 975 } 976 qdf_export_symbol(utils_dfs_reg_update_nol_ch); 977 978 uint8_t utils_dfs_freq_to_chan(uint32_t freq) 979 { 980 uint8_t chan; 981 982 if (freq == 0) 983 return 0; 984 985 if (freq > DFS_24_GHZ_BASE_FREQ && freq < DFS_CHAN_14_FREQ) 986 chan = ((freq - DFS_24_GHZ_BASE_FREQ) / DFS_CHAN_SPACING_5MHZ); 987 else if (freq == DFS_CHAN_14_FREQ) 988 chan = DFS_24_GHZ_CHANNEL_14; 989 else if ((freq > DFS_24_GHZ_BASE_FREQ) && (freq < DFS_5_GHZ_BASE_FREQ)) 990 chan = (((freq - DFS_CHAN_15_FREQ) / DFS_CHAN_SPACING_20MHZ) + 991 DFS_24_GHZ_CHANNEL_15); 992 else 993 chan = (freq - DFS_5_GHZ_BASE_FREQ) / DFS_CHAN_SPACING_5MHZ; 994 995 return chan; 996 } 997 qdf_export_symbol(utils_dfs_freq_to_chan); 998 999 uint32_t utils_dfs_chan_to_freq(uint8_t chan) 1000 { 1001 if (chan == 0) 1002 return 0; 1003 1004 if (chan < DFS_24_GHZ_CHANNEL_14) 1005 return DFS_24_GHZ_BASE_FREQ + (chan * DFS_CHAN_SPACING_5MHZ); 1006 else if (chan == DFS_24_GHZ_CHANNEL_14) 1007 return DFS_CHAN_14_FREQ; 1008 else if (chan < DFS_24_GHZ_CHANNEL_27) 1009 return DFS_CHAN_15_FREQ + ((chan - DFS_24_GHZ_CHANNEL_15) * 1010 DFS_CHAN_SPACING_20MHZ); 1011 else if (chan == DFS_5_GHZ_CHANNEL_170) 1012 return DFS_CHAN_170_FREQ; 1013 else 1014 return DFS_5_GHZ_BASE_FREQ + (chan * DFS_CHAN_SPACING_5MHZ); 1015 } 1016 qdf_export_symbol(utils_dfs_chan_to_freq); 1017 1018 #ifdef QCA_MCL_DFS_SUPPORT 1019 QDF_STATUS utils_dfs_mark_leaking_ch(struct wlan_objmgr_pdev *pdev, 1020 enum phy_ch_width ch_width, 1021 uint8_t temp_ch_lst_sz, 1022 uint8_t *temp_ch_lst) 1023 { 1024 struct wlan_dfs *dfs = NULL; 1025 1026 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 1027 if (!dfs) { 1028 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); 1029 return QDF_STATUS_E_FAILURE; 1030 } 1031 1032 return dfs_mark_leaking_ch(dfs, ch_width, temp_ch_lst_sz, temp_ch_lst); 1033 } 1034 qdf_export_symbol(utils_dfs_mark_leaking_ch); 1035 #endif 1036 1037 int utils_get_dfsdomain(struct wlan_objmgr_pdev *pdev) 1038 { 1039 enum dfs_reg dfsdomain; 1040 1041 wlan_reg_get_dfs_region(pdev, &dfsdomain); 1042 1043 return dfsdomain; 1044 } 1045 1046 uint16_t utils_dfs_get_cur_rd(struct wlan_objmgr_pdev *pdev) 1047 { 1048 struct cur_regdmn_info cur_regdmn; 1049 1050 wlan_reg_get_curr_regdomain(pdev, &cur_regdmn); 1051 1052 return cur_regdmn.regdmn_pair_id; 1053 } 1054 1055 #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST) 1056 QDF_STATUS utils_dfs_is_spoof_check_failed(struct wlan_objmgr_pdev *pdev, 1057 bool *is_spoof_check_failed) 1058 { 1059 struct wlan_dfs *dfs; 1060 1061 if (!tgt_dfs_is_pdev_5ghz(pdev)) 1062 return QDF_STATUS_SUCCESS; 1063 1064 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 1065 if (!dfs) { 1066 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is null"); 1067 return QDF_STATUS_E_FAILURE; 1068 } 1069 1070 *is_spoof_check_failed = dfs->dfs_spoof_check_failed; 1071 1072 return QDF_STATUS_SUCCESS; 1073 } 1074 1075 qdf_export_symbol(utils_dfs_is_spoof_check_failed); 1076 #endif 1077