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