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 QDF_STATUS utils_dfs_get_usenol(struct wlan_objmgr_pdev *pdev, uint16_t *usenol) 251 { 252 struct wlan_dfs *dfs; 253 254 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 255 if (!dfs) 256 return QDF_STATUS_E_FAILURE; 257 258 *usenol = dfs_get_use_nol(dfs); 259 260 return QDF_STATUS_SUCCESS; 261 } 262 qdf_export_symbol(utils_dfs_get_usenol); 263 264 QDF_STATUS utils_dfs_radar_disable(struct wlan_objmgr_pdev *pdev) 265 { 266 struct wlan_dfs *dfs; 267 268 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 269 if (!dfs) 270 return QDF_STATUS_E_FAILURE; 271 272 dfs_radar_disable(dfs); 273 274 return QDF_STATUS_SUCCESS; 275 } 276 qdf_export_symbol(utils_dfs_radar_disable); 277 278 QDF_STATUS utils_dfs_set_update_nol_flag(struct wlan_objmgr_pdev *pdev, 279 bool val) 280 { 281 struct wlan_dfs *dfs; 282 283 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 284 if (!dfs) 285 return QDF_STATUS_E_FAILURE; 286 287 dfs_set_update_nol_flag(dfs, val); 288 289 return QDF_STATUS_SUCCESS; 290 } 291 qdf_export_symbol(utils_dfs_set_update_nol_flag); 292 293 QDF_STATUS utils_dfs_get_update_nol_flag(struct wlan_objmgr_pdev *pdev, 294 bool *nol_flag) 295 { 296 struct wlan_dfs *dfs; 297 298 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 299 if (!dfs) 300 return QDF_STATUS_E_FAILURE; 301 302 *nol_flag = dfs_get_update_nol_flag(dfs); 303 304 return QDF_STATUS_SUCCESS; 305 } 306 qdf_export_symbol(utils_dfs_get_update_nol_flag); 307 308 QDF_STATUS utils_dfs_get_dfs_use_nol(struct wlan_objmgr_pdev *pdev, 309 int *dfs_use_nol) 310 { 311 struct wlan_dfs *dfs; 312 313 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 314 if (!dfs) 315 return QDF_STATUS_E_FAILURE; 316 317 *dfs_use_nol = dfs_get_use_nol(dfs); 318 319 return QDF_STATUS_SUCCESS; 320 } 321 qdf_export_symbol(utils_dfs_get_dfs_use_nol); 322 323 QDF_STATUS utils_dfs_get_nol_timeout(struct wlan_objmgr_pdev *pdev, 324 int *dfs_nol_timeout) 325 { 326 struct wlan_dfs *dfs; 327 328 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 329 if (!dfs) 330 return QDF_STATUS_E_FAILURE; 331 332 *dfs_nol_timeout = dfs_get_nol_timeout(dfs); 333 334 return QDF_STATUS_SUCCESS; 335 } 336 qdf_export_symbol(utils_dfs_get_nol_timeout); 337 338 QDF_STATUS utils_dfs_nol_addchan(struct wlan_objmgr_pdev *pdev, 339 uint16_t freq, 340 uint32_t dfs_nol_timeout) 341 { 342 struct wlan_dfs *dfs; 343 344 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 345 if (!dfs) 346 return QDF_STATUS_E_FAILURE; 347 348 DFS_NOL_ADD_CHAN_LOCKED(dfs, freq, dfs_nol_timeout); 349 350 return QDF_STATUS_SUCCESS; 351 } 352 qdf_export_symbol(utils_dfs_nol_addchan); 353 354 QDF_STATUS utils_dfs_nol_update(struct wlan_objmgr_pdev *pdev) 355 { 356 struct wlan_dfs *dfs; 357 358 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 359 if (!dfs) 360 return QDF_STATUS_E_FAILURE; 361 362 dfs_nol_update(dfs); 363 364 return QDF_STATUS_SUCCESS; 365 } 366 qdf_export_symbol(utils_dfs_nol_update); 367 368 QDF_STATUS utils_dfs_second_segment_radar_disable(struct wlan_objmgr_pdev *pdev) 369 { 370 struct wlan_dfs *dfs; 371 372 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 373 if (!dfs) 374 return QDF_STATUS_E_FAILURE; 375 376 dfs_second_segment_radar_disable(dfs); 377 378 return QDF_STATUS_SUCCESS; 379 } 380 381 QDF_STATUS utils_dfs_is_ignore_dfs(struct wlan_objmgr_pdev *pdev, 382 bool *ignore_dfs) 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 *ignore_dfs = dfs->dfs_ignore_dfs; 391 392 return QDF_STATUS_SUCCESS; 393 } 394 qdf_export_symbol(utils_dfs_is_ignore_dfs); 395 396 QDF_STATUS utils_dfs_is_cac_valid(struct wlan_objmgr_pdev *pdev, 397 bool *is_cac_valid) 398 { 399 struct wlan_dfs *dfs; 400 401 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 402 if (!dfs) 403 return QDF_STATUS_E_FAILURE; 404 405 *is_cac_valid = dfs->dfs_cac_valid; 406 407 return QDF_STATUS_SUCCESS; 408 } 409 qdf_export_symbol(utils_dfs_is_cac_valid); 410 411 QDF_STATUS utils_dfs_is_ignore_cac(struct wlan_objmgr_pdev *pdev, 412 bool *ignore_cac) 413 { 414 struct wlan_dfs *dfs; 415 416 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 417 if (!dfs) 418 return QDF_STATUS_E_FAILURE; 419 420 *ignore_cac = dfs->dfs_ignore_cac; 421 422 /* 423 * This is needed as, if after channel bandwidth reduction, channel 424 * change occurs using dothchanswitch or chan commands, resetting. 425 * dfs->dfs_ignore_cac will make sure we not skip CAC on the new channel 426 */ 427 428 if (dfs->dfs_bw_reduced) 429 dfs->dfs_ignore_cac = 0; 430 431 return QDF_STATUS_SUCCESS; 432 } 433 qdf_export_symbol(utils_dfs_is_ignore_cac); 434 435 QDF_STATUS utils_dfs_set_cac_timer_running(struct wlan_objmgr_pdev *pdev, 436 int val) 437 { 438 struct wlan_dfs *dfs; 439 440 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 441 if (!dfs) 442 return QDF_STATUS_E_FAILURE; 443 444 dfs->dfs_cac_timer_running = val; 445 446 return QDF_STATUS_SUCCESS; 447 } 448 qdf_export_symbol(utils_dfs_set_cac_timer_running); 449 450 QDF_STATUS utils_dfs_get_nol_chfreq_and_chwidth(struct wlan_objmgr_pdev *pdev, 451 void *nollist, 452 uint32_t *nol_chfreq, 453 uint32_t *nol_chwidth, 454 int index) 455 { 456 struct wlan_dfs *dfs; 457 458 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 459 if (!dfs) 460 return QDF_STATUS_E_FAILURE; 461 462 dfs_get_nol_chfreq_and_chwidth(nollist, nol_chfreq, nol_chwidth, index); 463 464 return QDF_STATUS_SUCCESS; 465 } 466 qdf_export_symbol(utils_dfs_get_nol_chfreq_and_chwidth); 467 468 QDF_STATUS utils_dfs_update_cur_chan_flags(struct wlan_objmgr_pdev *pdev, 469 uint64_t flags, 470 uint16_t flagext) 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_update_cur_chan_flags(dfs, flags, flagext); 479 480 return QDF_STATUS_SUCCESS; 481 } 482 483 static void utils_dfs_get_max_phy_mode(struct wlan_objmgr_pdev *pdev, 484 uint32_t *phy_mode) 485 { 486 return; 487 } 488 489 static void utils_dfs_get_max_sup_width(struct wlan_objmgr_pdev *pdev, 490 uint8_t *ch_width) 491 { 492 return; 493 } 494 495 /** 496 * utils_dfs_get_chan_list() - Get channel list from regdb based on current 497 * operating channel. 498 * @pdev: Pointer to DFS pdev object. 499 * @chan_list: Pointer to current channel list 500 * @num_chan: number of channels in the current channel list. 501 */ 502 #ifndef QCA_DFS_USE_POLICY_MANAGER 503 static void utils_dfs_get_chan_list(struct wlan_objmgr_pdev *pdev, 504 struct dfs_channel *chan_list, uint32_t *num_chan) 505 { 506 int i = 0, j = 0; 507 enum channel_state state; 508 struct regulatory_channel *cur_chan_list; 509 struct wlan_dfs *dfs; 510 511 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 512 if (!dfs) 513 return; 514 515 cur_chan_list = qdf_mem_malloc(NUM_CHANNELS * 516 sizeof(struct regulatory_channel)); 517 if (!cur_chan_list) { 518 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, "fail to alloc"); 519 *num_chan = 0; 520 return; 521 } 522 523 if (wlan_reg_get_current_chan_list( 524 pdev, cur_chan_list) != QDF_STATUS_SUCCESS) { 525 *num_chan = 0; 526 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, 527 "failed to get curr channel list"); 528 return; 529 } 530 531 for (i = 0; i < NUM_CHANNELS; i++) { 532 state = cur_chan_list[i].state; 533 if (state == CHANNEL_STATE_DFS || 534 state == CHANNEL_STATE_ENABLE) { 535 chan_list[j].dfs_ch_ieee = cur_chan_list[i].chan_num; 536 chan_list[j].dfs_ch_freq = cur_chan_list[i].center_freq; 537 if (state == CHANNEL_STATE_DFS) 538 chan_list[j].dfs_ch_flagext = 539 WLAN_CHAN_DFS; 540 j++; 541 } 542 } 543 *num_chan = j; 544 qdf_mem_free(cur_chan_list); 545 546 return; 547 } 548 549 /** 550 * utils_dfs_get_channel_list() - Get channel list from regdb component based 551 * on current channel list. 552 * @pdev: Pointer to pdev structure. 553 * @chan_list: Pointer to regdb channel list. 554 * @num_chan: number of channels. 555 * 556 * Get regdb channel list based on dfs current channel. 557 * ex: When AP is operating in 5GHz channel, filter 2.4GHz and 4.9GHZ channels 558 * so that the random channel function does not select either 2.4GHz or 4.9GHz 559 * channel. 560 */ 561 static void utils_dfs_get_channel_list(struct wlan_objmgr_pdev *pdev, 562 struct dfs_channel *chan_list, uint32_t *num_chan) 563 { 564 struct dfs_channel *tmp_chan_list = NULL; 565 struct wlan_dfs *dfs; 566 bool is_curchan_5g; 567 bool is_curchan_24g; 568 bool is_curchan_49g; 569 uint32_t chan_num; 570 uint32_t center_freq; 571 uint16_t flagext; 572 int i, j = 0; 573 574 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 575 if (!dfs) { 576 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); 577 return; 578 } 579 580 tmp_chan_list = qdf_mem_malloc(*num_chan * sizeof(*tmp_chan_list)); 581 if (!tmp_chan_list) { 582 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, "mem alloc failed"); 583 return; 584 } 585 586 utils_dfs_get_chan_list(pdev, tmp_chan_list, num_chan); 587 588 chan_num = dfs->dfs_curchan->dfs_ch_ieee; 589 center_freq = dfs->dfs_curchan->dfs_ch_freq; 590 is_curchan_5g = WLAN_REG_IS_5GHZ_CH(chan_num); 591 is_curchan_24g = WLAN_REG_IS_24GHZ_CH(chan_num); 592 is_curchan_49g = WLAN_REG_IS_49GHZ_FREQ(center_freq); 593 594 for (i = 0; i < *num_chan; i++) { 595 chan_num = tmp_chan_list[i].dfs_ch_ieee; 596 center_freq = tmp_chan_list[i].dfs_ch_freq; 597 flagext = tmp_chan_list[i].dfs_ch_flagext; 598 599 if (!dfs_mlme_check_allowed_prim_chanlist(pdev, chan_num)) 600 continue; 601 602 if ((is_curchan_5g) && WLAN_REG_IS_5GHZ_CH(chan_num)) { 603 chan_list[j].dfs_ch_ieee = chan_num; 604 chan_list[j].dfs_ch_freq = center_freq; 605 chan_list[j].dfs_ch_flagext = flagext; 606 j++; 607 } else if ((is_curchan_24g) && 608 WLAN_REG_IS_24GHZ_CH(chan_num)) { 609 chan_list[j].dfs_ch_ieee = chan_num; 610 chan_list[j].dfs_ch_freq = center_freq; 611 j++; 612 } else if ((is_curchan_49g) && 613 WLAN_REG_IS_49GHZ_FREQ(center_freq)) { 614 chan_list[j].dfs_ch_ieee = chan_num; 615 chan_list[j].dfs_ch_freq = center_freq; 616 j++; 617 } 618 } 619 620 *num_chan = j; 621 622 qdf_mem_free(tmp_chan_list); 623 } 624 625 #else 626 627 static void utils_dfs_get_chan_list(struct wlan_objmgr_pdev *pdev, 628 struct dfs_channel *chan_list, uint32_t *num_chan) 629 { 630 uint8_t pcl_ch[QDF_MAX_NUM_CHAN] = {0}; 631 uint8_t weight_list[QDF_MAX_NUM_CHAN] = {0}; 632 uint32_t len; 633 uint32_t weight_len; 634 int i; 635 struct wlan_objmgr_psoc *psoc; 636 uint32_t conn_count = 0; 637 638 psoc = wlan_pdev_get_psoc(pdev); 639 if (!psoc) { 640 *num_chan = 0; 641 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "null psoc"); 642 return; 643 } 644 645 len = QDF_ARRAY_SIZE(pcl_ch); 646 weight_len = QDF_ARRAY_SIZE(weight_list); 647 conn_count = policy_mgr_mode_specific_connection_count( 648 psoc, PM_SAP_MODE, NULL); 649 if (0 == conn_count) 650 policy_mgr_get_pcl(psoc, PM_SAP_MODE, pcl_ch, 651 &len, weight_list, weight_len); 652 else 653 policy_mgr_get_pcl_for_existing_conn(psoc, PM_SAP_MODE, pcl_ch, 654 &len, weight_list, weight_len, true); 655 656 if (*num_chan < len) { 657 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 658 "Invalid len src=%d, dst=%d", 659 *num_chan, len); 660 *num_chan = 0; 661 return; 662 } 663 664 for (i = 0; i < len; i++) { 665 chan_list[i].dfs_ch_ieee = pcl_ch[i]; 666 chan_list[i].dfs_ch_freq = 667 wlan_reg_chan_to_freq(pdev, pcl_ch[i]); 668 } 669 *num_chan = i; 670 dfs_info(NULL, WLAN_DEBUG_DFS_ALWAYS, "num channels %d", i); 671 } 672 673 /** 674 * utils_dfs_get_channel_list() - Wrapper function to get channel list from 675 * regdb component. 676 * @pdev: Pointer to pdev structure. 677 * @chan_list: Pointer to regdb channel list. 678 * @num_chan: number of channels. 679 */ 680 static void utils_dfs_get_channel_list(struct wlan_objmgr_pdev *pdev, 681 struct dfs_channel *chan_list, uint32_t *num_chan) 682 { 683 utils_dfs_get_chan_list(pdev, chan_list, num_chan); 684 } 685 #endif 686 687 QDF_STATUS utils_dfs_get_random_channel( 688 struct wlan_objmgr_pdev *pdev, 689 uint16_t flags, 690 struct ch_params *ch_params, 691 uint32_t *hw_mode, 692 uint8_t *target_chan, 693 struct dfs_acs_info *acs_info) 694 { 695 uint32_t dfs_reg; 696 uint32_t num_chan = NUM_CHANNELS; 697 struct wlan_dfs *dfs = NULL; 698 struct wlan_objmgr_psoc *psoc; 699 struct dfs_channel *chan_list = NULL; 700 struct dfs_channel cur_chan; 701 QDF_STATUS status = QDF_STATUS_E_FAILURE; 702 703 *target_chan = 0; 704 psoc = wlan_pdev_get_psoc(pdev); 705 if (!psoc) { 706 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null psoc"); 707 goto random_chan_error; 708 } 709 710 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 711 if (!dfs) { 712 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); 713 goto random_chan_error; 714 } 715 716 wlan_reg_get_dfs_region(pdev, &dfs_reg); 717 chan_list = qdf_mem_malloc(num_chan * sizeof(*chan_list)); 718 if (!chan_list) { 719 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, "mem alloc failed"); 720 goto random_chan_error; 721 } 722 723 utils_dfs_get_channel_list(pdev, chan_list, &num_chan); 724 if (!num_chan) { 725 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "zero channels"); 726 goto random_chan_error; 727 } 728 729 cur_chan.dfs_ch_vhtop_ch_freq_seg1 = ch_params->center_freq_seg0; 730 cur_chan.dfs_ch_vhtop_ch_freq_seg2 = ch_params->center_freq_seg1; 731 732 if (!ch_params->ch_width) 733 utils_dfs_get_max_sup_width(pdev, 734 (uint8_t *)&ch_params->ch_width); 735 736 *target_chan = dfs_prepare_random_channel(dfs, chan_list, 737 num_chan, flags, (uint8_t *)&ch_params->ch_width, 738 &cur_chan, (uint8_t)dfs_reg, acs_info); 739 740 ch_params->center_freq_seg0 = cur_chan.dfs_ch_vhtop_ch_freq_seg1; 741 ch_params->center_freq_seg1 = cur_chan.dfs_ch_vhtop_ch_freq_seg2; 742 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 743 "input width=%d", ch_params->ch_width); 744 745 if (*target_chan) { 746 wlan_reg_set_channel_params(pdev, 747 *target_chan, 0, ch_params); 748 utils_dfs_get_max_phy_mode(pdev, hw_mode); 749 status = QDF_STATUS_SUCCESS; 750 } 751 752 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 753 "ch=%d, seg0=%d, seg1=%d, width=%d", 754 *target_chan, ch_params->center_freq_seg0, 755 ch_params->center_freq_seg1, ch_params->ch_width); 756 757 random_chan_error: 758 qdf_mem_free(chan_list); 759 760 return status; 761 } 762 qdf_export_symbol(utils_dfs_get_random_channel); 763 764 QDF_STATUS utils_dfs_bw_reduced_channel( 765 struct wlan_objmgr_pdev *pdev, 766 uint16_t flags, 767 struct ch_params *ch_params, 768 uint32_t *hw_mode, 769 uint8_t *target_chan) 770 { 771 struct wlan_dfs *dfs = NULL; 772 struct wlan_objmgr_psoc *psoc; 773 enum channel_state ch_state; 774 QDF_STATUS status = QDF_STATUS_E_FAILURE; 775 776 *target_chan = 0; 777 psoc = wlan_pdev_get_psoc(pdev); 778 if (!psoc) { 779 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null psoc"); 780 return status; 781 } 782 783 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 784 if (!dfs) { 785 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); 786 return status; 787 } 788 789 ch_state = reg_get_channel_state(pdev, dfs->dfs_curchan->dfs_ch_ieee); 790 791 if (ch_state == CHANNEL_STATE_DFS || 792 ch_state == CHANNEL_STATE_ENABLE) { 793 ch_params->center_freq_seg0 = 794 dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg1; 795 ch_params->center_freq_seg1 = 796 dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2; 797 /*If bandwidth reduction is applied, 798 * dfs_ignore_cac ensures we skip CAC. 799 */ 800 dfs->dfs_ignore_cac = 1; 801 dfs->dfs_bw_reduced = 1; 802 wlan_reg_set_channel_params(pdev, 803 dfs->dfs_curchan->dfs_ch_ieee, 804 0, ch_params); 805 806 *target_chan = dfs->dfs_curchan->dfs_ch_ieee; 807 utils_dfs_get_max_phy_mode(pdev, hw_mode); 808 809 return QDF_STATUS_SUCCESS; 810 } 811 812 return status; 813 } 814 815 #ifdef QCA_DFS_NOL_PLATFORM_DRV_SUPPORT 816 void utils_dfs_init_nol(struct wlan_objmgr_pdev *pdev) 817 { 818 struct wlan_dfs *dfs; 819 struct wlan_objmgr_psoc *psoc; 820 qdf_device_t qdf_dev; 821 struct dfs_nol_info dfs_nolinfo; 822 int len; 823 824 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 825 psoc = wlan_pdev_get_psoc(pdev); 826 if (!dfs || !psoc) { 827 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, 828 "dfs %pK, psoc %pK", dfs, psoc); 829 return; 830 } 831 832 qdf_dev = psoc->soc_objmgr.qdf_dev; 833 if (!qdf_dev->dev) { 834 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null device"); 835 return; 836 } 837 838 qdf_mem_zero(&dfs_nolinfo, sizeof(dfs_nolinfo)); 839 len = pld_wlan_get_dfs_nol(qdf_dev->dev, (void *)&dfs_nolinfo, 840 (uint16_t)sizeof(dfs_nolinfo)); 841 if (len > 0) { 842 dfs_set_nol(dfs, dfs_nolinfo.dfs_nol, dfs_nolinfo.num_chans); 843 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "nol channels in pld"); 844 DFS_PRINT_NOL_LOCKED(dfs); 845 } else { 846 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "no nol in pld"); 847 } 848 } 849 #endif 850 qdf_export_symbol(utils_dfs_init_nol); 851 852 #ifndef QCA_DFS_NOL_PLATFORM_DRV_SUPPORT 853 void utils_dfs_save_nol(struct wlan_objmgr_pdev *pdev) 854 { 855 } 856 #else 857 void utils_dfs_save_nol(struct wlan_objmgr_pdev *pdev) 858 { 859 struct dfs_nol_info dfs_nolinfo; 860 struct wlan_dfs *dfs = NULL; 861 struct wlan_objmgr_psoc *psoc; 862 qdf_device_t qdf_dev; 863 int num_chans = 0; 864 865 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 866 if (!dfs) { 867 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); 868 return; 869 } 870 871 psoc = wlan_pdev_get_psoc(pdev); 872 if (!psoc) { 873 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null psoc"); 874 return; 875 } 876 877 qdf_dev = psoc->soc_objmgr.qdf_dev; 878 if (!qdf_dev->dev) { 879 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null device"); 880 return; 881 } 882 883 qdf_mem_zero(&dfs_nolinfo, sizeof(dfs_nolinfo)); 884 DFS_GET_NOL_LOCKED(dfs, dfs_nolinfo.dfs_nol, &num_chans); 885 if (num_chans > 0) { 886 887 if (num_chans > DFS_MAX_NOL_CHANNEL) 888 dfs_nolinfo.num_chans = DFS_MAX_NOL_CHANNEL; 889 else 890 dfs_nolinfo.num_chans = num_chans; 891 892 pld_wlan_set_dfs_nol(qdf_dev->dev, (void *)&dfs_nolinfo, 893 (uint16_t)sizeof(dfs_nolinfo)); 894 } 895 } 896 #endif 897 qdf_export_symbol(utils_dfs_save_nol); 898 899 void utils_dfs_print_nol_channels(struct wlan_objmgr_pdev *pdev) 900 { 901 struct wlan_dfs *dfs = NULL; 902 903 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 904 if (!dfs) { 905 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); 906 return; 907 } 908 909 DFS_PRINT_NOL_LOCKED(dfs); 910 } 911 qdf_export_symbol(utils_dfs_print_nol_channels); 912 913 void utils_dfs_clear_nol_channels(struct wlan_objmgr_pdev *pdev) 914 { 915 struct wlan_dfs *dfs = NULL; 916 917 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 918 if (!dfs) { 919 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); 920 return; 921 } 922 923 /* First print list */ 924 DFS_PRINT_NOL_LOCKED(dfs); 925 926 /* clear local cache first */ 927 dfs_nol_timer_cleanup(dfs); 928 dfs_nol_update(dfs); 929 930 /* 931 * update platform driver nol list with local cache which is zero, 932 * cleared in above step, so this will clear list in platform driver. 933 */ 934 utils_dfs_save_nol(pdev); 935 } 936 qdf_export_symbol(utils_dfs_clear_nol_channels); 937 938 void utils_dfs_reg_update_nol_ch(struct wlan_objmgr_pdev *pdev, 939 uint8_t *ch_list, 940 uint8_t num_ch, 941 bool nol_ch) 942 { 943 /* TODO : Need locking?*/ 944 wlan_reg_update_nol_ch(pdev, ch_list, num_ch, nol_ch); 945 } 946 qdf_export_symbol(utils_dfs_reg_update_nol_ch); 947 948 uint8_t utils_dfs_freq_to_chan(uint32_t freq) 949 { 950 uint8_t chan; 951 952 if (freq == 0) 953 return 0; 954 955 if (freq > DFS_24_GHZ_BASE_FREQ && freq < DFS_CHAN_14_FREQ) 956 chan = ((freq - DFS_24_GHZ_BASE_FREQ) / DFS_CHAN_SPACING_5MHZ); 957 else if (freq == DFS_CHAN_14_FREQ) 958 chan = DFS_24_GHZ_CHANNEL_14; 959 else if ((freq > DFS_24_GHZ_BASE_FREQ) && (freq < DFS_5_GHZ_BASE_FREQ)) 960 chan = (((freq - DFS_CHAN_15_FREQ) / DFS_CHAN_SPACING_20MHZ) + 961 DFS_24_GHZ_CHANNEL_15); 962 else 963 chan = (freq - DFS_5_GHZ_BASE_FREQ) / DFS_CHAN_SPACING_5MHZ; 964 965 return chan; 966 } 967 qdf_export_symbol(utils_dfs_freq_to_chan); 968 969 uint32_t utils_dfs_chan_to_freq(uint8_t chan) 970 { 971 if (chan == 0) 972 return 0; 973 974 if (chan < DFS_24_GHZ_CHANNEL_14) 975 return DFS_24_GHZ_BASE_FREQ + (chan * DFS_CHAN_SPACING_5MHZ); 976 else if (chan == DFS_24_GHZ_CHANNEL_14) 977 return DFS_CHAN_14_FREQ; 978 else if (chan < DFS_24_GHZ_CHANNEL_27) 979 return DFS_CHAN_15_FREQ + ((chan - DFS_24_GHZ_CHANNEL_15) * 980 DFS_CHAN_SPACING_20MHZ); 981 else if (chan == DFS_5_GHZ_CHANNEL_170) 982 return DFS_CHAN_170_FREQ; 983 else 984 return DFS_5_GHZ_BASE_FREQ + (chan * DFS_CHAN_SPACING_5MHZ); 985 } 986 qdf_export_symbol(utils_dfs_chan_to_freq); 987 988 #ifdef QCA_MCL_DFS_SUPPORT 989 QDF_STATUS utils_dfs_mark_leaking_ch(struct wlan_objmgr_pdev *pdev, 990 enum phy_ch_width ch_width, 991 uint8_t temp_ch_lst_sz, 992 uint8_t *temp_ch_lst) 993 { 994 struct wlan_dfs *dfs = NULL; 995 996 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 997 if (!dfs) { 998 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); 999 return QDF_STATUS_E_FAILURE; 1000 } 1001 1002 return dfs_mark_leaking_ch(dfs, ch_width, temp_ch_lst_sz, temp_ch_lst); 1003 } 1004 qdf_export_symbol(utils_dfs_mark_leaking_ch); 1005 #endif 1006 1007 int utils_get_dfsdomain(struct wlan_objmgr_pdev *pdev) 1008 { 1009 enum dfs_reg dfsdomain; 1010 1011 wlan_reg_get_dfs_region(pdev, &dfsdomain); 1012 1013 return dfsdomain; 1014 } 1015 1016 uint16_t utils_dfs_get_cur_rd(struct wlan_objmgr_pdev *pdev) 1017 { 1018 struct cur_regdmn_info cur_regdmn; 1019 1020 wlan_reg_get_curr_regdomain(pdev, &cur_regdmn); 1021 1022 return cur_regdmn.regdmn_pair_id; 1023 } 1024 1025 #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST) 1026 QDF_STATUS utils_dfs_is_spoof_check_failed(struct wlan_objmgr_pdev *pdev, 1027 bool *is_spoof_check_failed) 1028 { 1029 struct wlan_dfs *dfs; 1030 1031 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 1032 if (!dfs) { 1033 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); 1034 return QDF_STATUS_E_FAILURE; 1035 } 1036 1037 *is_spoof_check_failed = dfs->dfs_spoof_check_failed; 1038 1039 return QDF_STATUS_SUCCESS; 1040 } 1041 1042 qdf_export_symbol(utils_dfs_is_spoof_check_failed); 1043 #endif 1044