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