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