1 /* 2 * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. 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: reg_utils.c 22 * This file defines the APIs to set and get the regulatory variables. 23 */ 24 25 #include <wlan_cmn.h> 26 #include <reg_services_public_struct.h> 27 #include <wlan_objmgr_psoc_obj.h> 28 #include <wlan_objmgr_pdev_obj.h> 29 #include "reg_priv_objs.h" 30 #include "reg_utils.h" 31 #include "reg_callbacks.h" 32 #include "reg_db.h" 33 #include "reg_db_parser.h" 34 #include "reg_host_11d.h" 35 #include <scheduler_api.h> 36 #include <wlan_reg_services_api.h> 37 #include <qdf_platform.h> 38 #include "reg_services_common.h" 39 #include "reg_build_chan_list.h" 40 #include "wlan_cm_bss_score_param.h" 41 #include "qdf_str.h" 42 #include "wmi_unified_param.h" 43 44 #define DEFAULT_WORLD_REGDMN 0x60 45 #define FCC3_FCCA 0x3A 46 #define FCC6_FCCA 0x14 47 48 #define IS_VALID_PSOC_REG_OBJ(psoc_priv_obj) (psoc_priv_obj) 49 #define IS_VALID_PDEV_REG_OBJ(pdev_priv_obj) (pdev_priv_obj) 50 51 #ifdef CONFIG_CHAN_FREQ_API 52 bool reg_chan_has_dfs_attribute_for_freq(struct wlan_objmgr_pdev *pdev, 53 qdf_freq_t freq) 54 { 55 enum channel_enum ch_idx; 56 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; 57 58 ch_idx = reg_get_chan_enum_for_freq(freq); 59 60 if (reg_is_chan_enum_invalid(ch_idx)) 61 return false; 62 63 pdev_priv_obj = reg_get_pdev_obj(pdev); 64 65 if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { 66 reg_err("pdev reg obj is NULL"); 67 return false; 68 } 69 70 if (pdev_priv_obj->cur_chan_list[ch_idx].chan_flags & 71 REGULATORY_CHAN_RADAR) 72 return true; 73 74 return false; 75 } 76 #endif /* CONFIG_CHAN_FREQ_API */ 77 78 bool reg_is_world_ctry_code(uint16_t ctry_code) 79 { 80 if ((ctry_code & 0xFFF0) == DEFAULT_WORLD_REGDMN) 81 return true; 82 83 return false; 84 } 85 86 QDF_STATUS reg_read_current_country(struct wlan_objmgr_psoc *psoc, 87 uint8_t *country_code) 88 { 89 struct wlan_regulatory_psoc_priv_obj *psoc_reg; 90 91 if (!country_code) { 92 reg_err("country_code is NULL"); 93 return QDF_STATUS_E_INVAL; 94 } 95 96 psoc_reg = reg_get_psoc_obj(psoc); 97 if (!IS_VALID_PSOC_REG_OBJ(psoc_reg)) { 98 reg_err("psoc reg component is NULL"); 99 return QDF_STATUS_E_INVAL; 100 } 101 102 qdf_mem_copy(country_code, psoc_reg->cur_country, REG_ALPHA2_LEN + 1); 103 104 return QDF_STATUS_SUCCESS; 105 } 106 107 /** 108 * reg_set_default_country() - Read the default country for the regdomain 109 * @country: country code. 110 * 111 * Return: QDF_STATUS 112 */ 113 QDF_STATUS reg_set_default_country(struct wlan_objmgr_psoc *psoc, 114 uint8_t *country) 115 { 116 struct wlan_regulatory_psoc_priv_obj *psoc_reg; 117 118 if (!country) { 119 reg_err("country is NULL"); 120 return QDF_STATUS_E_INVAL; 121 } 122 123 psoc_reg = reg_get_psoc_obj(psoc); 124 if (!IS_VALID_PSOC_REG_OBJ(psoc_reg)) { 125 reg_err("psoc reg component is NULL"); 126 return QDF_STATUS_E_INVAL; 127 } 128 129 reg_info("set default_country: %s", country); 130 131 qdf_mem_copy(psoc_reg->def_country, country, REG_ALPHA2_LEN + 1); 132 133 return QDF_STATUS_SUCCESS; 134 } 135 136 bool reg_is_world_alpha2(uint8_t *alpha2) 137 { 138 if ((alpha2[0] == '0') && (alpha2[1] == '0')) 139 return true; 140 141 return false; 142 } 143 144 bool reg_is_us_alpha2(uint8_t *alpha2) 145 { 146 if ((alpha2[0] == 'U') && (alpha2[1] == 'S')) 147 return true; 148 149 return false; 150 } 151 152 bool reg_is_etsi_alpha2(uint8_t *alpha2) 153 { 154 if ((alpha2[0] == 'G') && (alpha2[1] == 'B')) 155 return true; 156 157 return false; 158 } 159 160 static 161 const char *reg_get_power_mode_string(uint16_t reg_dmn_pair_id) 162 { 163 switch (reg_dmn_pair_id) { 164 case FCC3_FCCA: 165 case FCC6_FCCA: 166 return "NON_VLP"; 167 default: 168 return "VLP"; 169 } 170 } 171 172 static bool reg_ctry_domain_supports_vlp(uint8_t *alpha2) 173 { 174 uint16_t i; 175 int no_of_countries; 176 177 reg_get_num_countries(&no_of_countries); 178 for (i = 0; i < no_of_countries; i++) { 179 if (g_all_countries[i].alpha2[0] == alpha2[0] && 180 g_all_countries[i].alpha2[1] == alpha2[1]) { 181 if (!qdf_str_cmp(reg_get_power_mode_string( 182 g_all_countries[i].reg_dmn_pair_id), "NON_VLP")) 183 return false; 184 else 185 return true; 186 } 187 } 188 return true; 189 } 190 191 bool reg_ctry_support_vlp(uint8_t *alpha2) 192 { 193 if (((alpha2[0] == 'A') && (alpha2[1] == 'E')) || 194 ((alpha2[0] == 'P') && (alpha2[1] == 'E')) || 195 ((alpha2[0] == 'U') && (alpha2[1] == 'S')) || 196 !reg_ctry_domain_supports_vlp(alpha2)) 197 return false; 198 else 199 return true; 200 } 201 202 static QDF_STATUS reg_set_non_offload_country(struct wlan_objmgr_pdev *pdev, 203 struct set_country *cc) 204 { 205 struct wlan_objmgr_psoc *psoc; 206 struct wlan_lmac_if_reg_tx_ops *tx_ops; 207 struct wlan_regulatory_psoc_priv_obj *psoc_reg; 208 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; 209 struct cc_regdmn_s rd; 210 uint8_t pdev_id; 211 uint8_t phy_id; 212 213 if (!pdev) { 214 reg_err("pdev is NULL"); 215 return QDF_STATUS_E_INVAL; 216 } 217 218 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 219 psoc = wlan_pdev_get_psoc(pdev); 220 tx_ops = reg_get_psoc_tx_ops(psoc); 221 if (tx_ops->get_phy_id_from_pdev_id) 222 tx_ops->get_phy_id_from_pdev_id(psoc, pdev_id, &phy_id); 223 else 224 phy_id = pdev_id; 225 226 psoc_reg = reg_get_psoc_obj(psoc); 227 if (!IS_VALID_PSOC_REG_OBJ(psoc_reg)) { 228 reg_err("psoc reg component is NULL"); 229 return QDF_STATUS_E_INVAL; 230 } 231 232 if (reg_is_world_alpha2(cc->country)) { 233 pdev_priv_obj = reg_get_pdev_obj(pdev); 234 if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { 235 reg_err("reg component pdev priv is NULL"); 236 psoc_reg->world_country_pending[phy_id] = false; 237 return QDF_STATUS_E_INVAL; 238 } 239 if (reg_is_world_ctry_code(pdev_priv_obj->def_region_domain)) 240 rd.cc.regdmn.reg_2g_5g_pair_id = 241 pdev_priv_obj->def_region_domain; 242 else 243 rd.cc.regdmn.reg_2g_5g_pair_id = DEFAULT_WORLD_REGDMN; 244 rd.flags = REGDMN_IS_SET; 245 } else { 246 qdf_mem_copy(rd.cc.alpha, cc->country, REG_ALPHA2_LEN + 1); 247 rd.flags = ALPHA_IS_SET; 248 } 249 250 reg_program_chan_list(pdev, &rd); 251 return QDF_STATUS_SUCCESS; 252 } 253 254 #ifdef WLAN_REG_PARTIAL_OFFLOAD 255 /** 256 * reg_restore_def_country_for_po() - API to restore country code to default 257 * value if given country is invalid for Partial Offload 258 * @offload_enabled: Is offload enabled 259 * @country: Country code 260 * @cc_country: Country code array 261 * Return- void 262 */ 263 static void reg_restore_def_country_for_po(bool offload_enabled, 264 uint8_t *country, 265 uint8_t cc_country[]){ 266 if (!offload_enabled && !reg_is_world_alpha2(country)) { 267 QDF_STATUS status; 268 269 status = reg_is_country_code_valid(country); 270 if (!QDF_IS_STATUS_SUCCESS(status)) { 271 reg_err("Unable to set country code: %s\n", country); 272 reg_err("Restoring to world domain"); 273 qdf_mem_copy(cc_country, REG_WORLD_ALPHA2, 274 REG_ALPHA2_LEN + 1); 275 } 276 } 277 } 278 #else 279 static void reg_restore_def_country_for_po(bool offload_enabled, 280 uint8_t *country, 281 uint8_t cc_country[]){ 282 } 283 #endif 284 285 QDF_STATUS reg_set_country(struct wlan_objmgr_pdev *pdev, 286 uint8_t *country) 287 { 288 struct wlan_regulatory_psoc_priv_obj *psoc_reg; 289 struct wlan_lmac_if_reg_tx_ops *tx_ops; 290 struct set_country cc; 291 struct wlan_objmgr_psoc *psoc; 292 uint8_t pdev_id; 293 uint8_t phy_id; 294 295 if (!pdev) { 296 reg_err("pdev is NULL"); 297 return QDF_STATUS_E_INVAL; 298 } 299 300 if (!country) { 301 reg_err("country code is NULL"); 302 return QDF_STATUS_E_INVAL; 303 } 304 305 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 306 307 psoc = wlan_pdev_get_psoc(pdev); 308 309 tx_ops = reg_get_psoc_tx_ops(psoc); 310 if (tx_ops->get_phy_id_from_pdev_id) 311 tx_ops->get_phy_id_from_pdev_id(psoc, pdev_id, &phy_id); 312 else 313 phy_id = pdev_id; 314 315 psoc_reg = reg_get_psoc_obj(psoc); 316 if (!IS_VALID_PSOC_REG_OBJ(psoc_reg)) { 317 reg_err("psoc reg component is NULL"); 318 return QDF_STATUS_E_INVAL; 319 } 320 321 if (!qdf_mem_cmp(psoc_reg->cur_country, country, REG_ALPHA2_LEN)) { 322 if (psoc_reg->cc_src == SOURCE_USERSPACE || 323 psoc_reg->cc_src == SOURCE_CORE) { 324 reg_debug("country is not different"); 325 return QDF_STATUS_E_INVAL; 326 } 327 } 328 329 reg_debug("programming new country: %s to firmware", country); 330 331 qdf_mem_copy(cc.country, country, REG_ALPHA2_LEN + 1); 332 /* 333 * Need firmware to send channel list event 334 * for all phys. Therefore set pdev_id to 0xFF. 335 */ 336 cc.pdev_id = WMI_HOST_PDEV_ID_SOC; 337 338 reg_restore_def_country_for_po(psoc_reg->offload_enabled, 339 country, 340 cc.country); 341 342 if (reg_is_world_alpha2(cc.country)) 343 psoc_reg->world_country_pending[phy_id] = true; 344 else 345 psoc_reg->new_user_ctry_pending[phy_id] = true; 346 347 if (psoc_reg->offload_enabled) { 348 tx_ops = reg_get_psoc_tx_ops(psoc); 349 if (tx_ops->set_country_code) { 350 tx_ops->set_country_code(psoc, &cc); 351 } else { 352 reg_err("country set fw handler not present"); 353 psoc_reg->new_user_ctry_pending[phy_id] = false; 354 return QDF_STATUS_E_FAULT; 355 } 356 } else { 357 return reg_set_non_offload_country(pdev, &cc); 358 } 359 360 return QDF_STATUS_SUCCESS; 361 } 362 363 QDF_STATUS reg_reset_country(struct wlan_objmgr_psoc *psoc) 364 { 365 struct wlan_regulatory_psoc_priv_obj *psoc_reg; 366 367 psoc_reg = reg_get_psoc_obj(psoc); 368 if (!IS_VALID_PSOC_REG_OBJ(psoc_reg)) { 369 reg_err("psoc reg component is NULL"); 370 return QDF_STATUS_E_INVAL; 371 } 372 373 qdf_mem_copy(psoc_reg->cur_country, 374 psoc_reg->def_country, 375 REG_ALPHA2_LEN + 1); 376 reg_debug("set cur_country %.2s", psoc_reg->cur_country); 377 378 return QDF_STATUS_SUCCESS; 379 } 380 381 QDF_STATUS reg_get_domain_from_country_code(v_REGDOMAIN_t *reg_domain_ptr, 382 const uint8_t *country_alpha2, 383 enum country_src source) 384 { 385 if (!reg_domain_ptr) { 386 reg_err("Invalid reg domain pointer"); 387 return QDF_STATUS_E_FAULT; 388 } 389 390 *reg_domain_ptr = 0; 391 392 if (!country_alpha2) { 393 reg_err("Country code is NULL"); 394 return QDF_STATUS_E_FAULT; 395 } 396 397 return QDF_STATUS_SUCCESS; 398 } 399 400 #ifdef CONFIG_REG_CLIENT 401 #ifdef CONFIG_BAND_6GHZ 402 QDF_STATUS 403 reg_get_6g_power_type_for_ctry(struct wlan_objmgr_psoc *psoc, 404 struct wlan_objmgr_pdev *pdev, 405 uint8_t *ap_ctry, uint8_t *sta_ctry, 406 enum reg_6g_ap_type *pwr_type_6g, 407 bool *ctry_code_match, 408 enum reg_6g_ap_type ap_pwr_type) 409 { 410 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; 411 412 *pwr_type_6g = ap_pwr_type; 413 pdev_priv_obj = reg_get_pdev_obj(pdev); 414 if (!pdev_priv_obj) { 415 reg_err("pdev priv obj null"); 416 return QDF_STATUS_E_FAILURE; 417 } 418 419 reg_debug("STA country: %c%c, AP country: %c%c, AP power type: %d", 420 sta_ctry[0], sta_ctry[1], ap_ctry[0], ap_ctry[1], 421 ap_pwr_type); 422 423 if (!qdf_mem_cmp(ap_ctry, sta_ctry, REG_ALPHA2_LEN)) { 424 *ctry_code_match = true; 425 if (ap_pwr_type == REG_VERY_LOW_POWER_AP) { 426 if (!pdev_priv_obj->reg_rules.num_of_6g_client_reg_rules[ap_pwr_type]) { 427 reg_err("VLP not supported, can't connect"); 428 return QDF_STATUS_E_NOSUPPORT; 429 } 430 } 431 return QDF_STATUS_SUCCESS; 432 } 433 434 *ctry_code_match = false; 435 /* 436 * If reg_info=0 not included, STA should operate in VLP mode. 437 * If STA country doesn't support VLP, do not return if Wi-Fi 438 * safe mode or RF test mode or enable relaxed connection policy, 439 * rather STA should operate in LPI mode. 440 * wlan_cm_get_check_6ghz_security API returns true if 441 * neither Safe mode nor RF test mode are enabled. 442 * wlan_cm_get_relaxed_6ghz_conn_policy API returns true if 443 * enabled. 444 */ 445 if (ap_pwr_type != REG_INDOOR_AP) { 446 if (wlan_reg_ctry_support_vlp(sta_ctry) && 447 wlan_reg_ctry_support_vlp(ap_ctry)) { 448 reg_debug("STA ctry doesn't match with AP ctry, switch to VLP"); 449 *pwr_type_6g = REG_VERY_LOW_POWER_AP; 450 } else { 451 reg_debug("AP or STA doesn't support VLP"); 452 *pwr_type_6g = REG_INDOOR_AP; 453 } 454 455 if (!wlan_reg_ctry_support_vlp(sta_ctry) && 456 wlan_cm_get_check_6ghz_security(psoc) && 457 !wlan_cm_get_relaxed_6ghz_conn_policy(psoc)) { 458 reg_err("VLP not supported, can't connect"); 459 return QDF_STATUS_E_NOSUPPORT; 460 } 461 } 462 463 if (ap_pwr_type == REG_INDOOR_AP) { 464 reg_debug("Indoor AP, allow STA IN LPI"); 465 *pwr_type_6g = REG_INDOOR_AP; 466 } 467 468 return QDF_STATUS_SUCCESS; 469 } 470 #else 471 QDF_STATUS 472 reg_get_6g_power_type_for_ctry(struct wlan_objmgr_psoc *psoc, 473 struct wlan_objmgr_pdev *pdev, 474 uint8_t *ap_ctry, uint8_t *sta_ctry, 475 enum reg_6g_ap_type *pwr_type_6g, 476 bool *ctry_code_match, 477 enum reg_6g_ap_type ap_pwr_type) 478 { 479 return QDF_STATUS_SUCCESS; 480 } 481 #endif 482 #endif 483 484 #ifdef FEATURE_WLAN_CH_AVOID_EXT 485 static inline 486 void reg_get_coex_unsafe_chan_nb_user_prefer( 487 struct wlan_regulatory_psoc_priv_obj 488 *psoc_priv_obj, 489 struct reg_config_vars config_vars) 490 { 491 psoc_priv_obj->coex_unsafe_chan_nb_user_prefer = 492 config_vars.coex_unsafe_chan_nb_user_prefer; 493 } 494 495 static inline 496 void reg_get_coex_unsafe_chan_reg_disable( 497 struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj, 498 struct reg_config_vars config_vars) 499 { 500 psoc_priv_obj->coex_unsafe_chan_reg_disable = 501 config_vars.coex_unsafe_chan_reg_disable; 502 } 503 #else 504 static inline 505 void reg_get_coex_unsafe_chan_nb_user_prefer( 506 struct wlan_regulatory_psoc_priv_obj 507 *psoc_priv_obj, 508 struct reg_config_vars config_vars) 509 { 510 } 511 512 static inline 513 void reg_get_coex_unsafe_chan_reg_disable( 514 struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj, 515 struct reg_config_vars config_vars) 516 { 517 } 518 #endif 519 520 #ifdef CONFIG_CHAN_FREQ_API 521 bool reg_is_passive_or_disable_for_pwrmode( 522 struct wlan_objmgr_pdev *pdev, 523 qdf_freq_t freq, 524 enum supported_6g_pwr_types in_6g_pwr_mode) 525 { 526 enum channel_state chan_state; 527 528 chan_state = reg_get_channel_state_for_pwrmode(pdev, freq, 529 in_6g_pwr_mode); 530 531 return (chan_state == CHANNEL_STATE_DFS) || 532 (chan_state == CHANNEL_STATE_DISABLE); 533 } 534 #endif /* CONFIG_CHAN_FREQ_API */ 535 536 #ifdef WLAN_FEATURE_DSRC 537 #ifdef CONFIG_CHAN_FREQ_API 538 bool reg_is_dsrc_freq(qdf_freq_t freq) 539 { 540 if (!REG_IS_5GHZ_FREQ(freq)) 541 return false; 542 543 if (!(freq >= REG_DSRC_START_FREQ && freq <= REG_DSRC_END_FREQ)) 544 return false; 545 546 return true; 547 } 548 #endif /*CONFIG_CHAN_FREQ_API*/ 549 #else 550 bool reg_is_etsi13_regdmn(struct wlan_objmgr_pdev *pdev) 551 { 552 struct cur_regdmn_info cur_reg_dmn; 553 QDF_STATUS status; 554 555 status = reg_get_curr_regdomain(pdev, &cur_reg_dmn); 556 if (status != QDF_STATUS_SUCCESS) { 557 reg_debug_rl("Failed to get reg domain"); 558 return false; 559 } 560 561 return reg_etsi13_regdmn(cur_reg_dmn.dmn_id_5g); 562 } 563 564 #ifdef CONFIG_CHAN_FREQ_API 565 bool reg_is_etsi13_srd_chan_for_freq(struct wlan_objmgr_pdev *pdev, 566 uint16_t freq) 567 { 568 if (!REG_IS_5GHZ_FREQ(freq)) 569 return false; 570 571 if (!(freq >= REG_ETSI13_SRD_START_FREQ && 572 freq <= REG_ETSI13_SRD_END_FREQ)) 573 return false; 574 575 return reg_is_etsi13_regdmn(pdev); 576 } 577 #endif /* CONFIG_CHAN_FREQ_API */ 578 579 bool reg_is_etsi13_srd_chan_allowed_master_mode(struct wlan_objmgr_pdev *pdev) 580 { 581 struct wlan_objmgr_psoc *psoc; 582 struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; 583 584 if (!pdev) { 585 reg_alert("pdev is NULL"); 586 return true; 587 } 588 psoc = wlan_pdev_get_psoc(pdev); 589 590 psoc_priv_obj = reg_get_psoc_obj(psoc); 591 if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) { 592 reg_alert("psoc reg component is NULL"); 593 return true; 594 } 595 596 return psoc_priv_obj->enable_srd_chan_in_master_mode && 597 reg_is_etsi13_regdmn(pdev); 598 } 599 #endif 600 601 QDF_STATUS reg_set_band(struct wlan_objmgr_pdev *pdev, uint32_t band_bitmap) 602 { 603 struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; 604 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; 605 struct wlan_objmgr_psoc *psoc; 606 QDF_STATUS status; 607 608 pdev_priv_obj = reg_get_pdev_obj(pdev); 609 610 if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { 611 reg_err("pdev reg component is NULL"); 612 return QDF_STATUS_E_INVAL; 613 } 614 615 if (pdev_priv_obj->band_capability == band_bitmap) { 616 reg_info("same band %d", band_bitmap); 617 return QDF_STATUS_SUCCESS; 618 } 619 620 psoc = wlan_pdev_get_psoc(pdev); 621 if (!psoc) { 622 reg_err("psoc is NULL"); 623 return QDF_STATUS_E_INVAL; 624 } 625 626 psoc_priv_obj = reg_get_psoc_obj(psoc); 627 if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) { 628 reg_err("psoc reg component is NULL"); 629 return QDF_STATUS_E_INVAL; 630 } 631 632 reg_info("set band bitmap: %d", band_bitmap); 633 pdev_priv_obj->band_capability = band_bitmap; 634 635 reg_compute_pdev_current_chan_list(pdev_priv_obj); 636 637 status = reg_send_scheduler_msg_sb(psoc, pdev); 638 639 return status; 640 } 641 642 QDF_STATUS reg_get_band(struct wlan_objmgr_pdev *pdev, 643 uint32_t *band_bitmap) 644 { 645 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; 646 647 pdev_priv_obj = reg_get_pdev_obj(pdev); 648 649 if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { 650 reg_err("pdev reg component is NULL"); 651 return QDF_STATUS_E_INVAL; 652 } 653 654 reg_debug("get band bitmap: %d", pdev_priv_obj->band_capability); 655 *band_bitmap = pdev_priv_obj->band_capability; 656 657 return QDF_STATUS_SUCCESS; 658 } 659 660 #ifdef DISABLE_CHANNEL_LIST 661 QDF_STATUS reg_restore_cached_channels(struct wlan_objmgr_pdev *pdev) 662 { 663 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; 664 struct wlan_objmgr_psoc *psoc; 665 QDF_STATUS status; 666 667 pdev_priv_obj = reg_get_pdev_obj(pdev); 668 if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { 669 reg_err("pdev reg component is NULL"); 670 return QDF_STATUS_E_INVAL; 671 } 672 673 psoc = wlan_pdev_get_psoc(pdev); 674 if (!psoc) { 675 reg_err("psoc is NULL"); 676 return QDF_STATUS_E_INVAL; 677 } 678 679 pdev_priv_obj->disable_cached_channels = false; 680 reg_compute_pdev_current_chan_list(pdev_priv_obj); 681 status = reg_send_scheduler_msg_sb(psoc, pdev); 682 return status; 683 } 684 685 QDF_STATUS reg_disable_cached_channels(struct wlan_objmgr_pdev *pdev) 686 { 687 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; 688 struct wlan_objmgr_psoc *psoc; 689 QDF_STATUS status; 690 691 pdev_priv_obj = reg_get_pdev_obj(pdev); 692 if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { 693 reg_err("pdev reg component is NULL"); 694 return QDF_STATUS_E_INVAL; 695 } 696 697 psoc = wlan_pdev_get_psoc(pdev); 698 if (!psoc) { 699 reg_err("psoc is NULL"); 700 return QDF_STATUS_E_INVAL; 701 } 702 703 pdev_priv_obj->disable_cached_channels = true; 704 reg_compute_pdev_current_chan_list(pdev_priv_obj); 705 status = reg_send_scheduler_msg_sb(psoc, pdev); 706 return status; 707 } 708 709 #ifdef CONFIG_CHAN_FREQ_API 710 QDF_STATUS reg_cache_channel_freq_state(struct wlan_objmgr_pdev *pdev, 711 uint32_t *channel_list, 712 uint32_t num_channels) 713 { 714 struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; 715 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; 716 struct wlan_objmgr_psoc *psoc; 717 uint16_t i, j; 718 719 pdev_priv_obj = reg_get_pdev_obj(pdev); 720 721 if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { 722 reg_err("pdev reg component is NULL"); 723 return QDF_STATUS_E_INVAL; 724 } 725 726 psoc = wlan_pdev_get_psoc(pdev); 727 if (!psoc) { 728 reg_err("psoc is NULL"); 729 return QDF_STATUS_E_INVAL; 730 } 731 732 psoc_priv_obj = reg_get_psoc_obj(psoc); 733 if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) { 734 reg_err("psoc reg component is NULL"); 735 return QDF_STATUS_E_INVAL; 736 } 737 if (pdev_priv_obj->num_cache_channels > 0) { 738 pdev_priv_obj->num_cache_channels = 0; 739 qdf_mem_zero(&pdev_priv_obj->cache_disable_chan_list, 740 sizeof(pdev_priv_obj->cache_disable_chan_list)); 741 } 742 743 for (i = 0; i < num_channels; i++) { 744 for (j = 0; j < NUM_CHANNELS; j++) { 745 if (channel_list[i] == pdev_priv_obj-> 746 cur_chan_list[j].center_freq) { 747 pdev_priv_obj-> 748 cache_disable_chan_list[i].center_freq = 749 channel_list[i]; 750 pdev_priv_obj-> 751 cache_disable_chan_list[i].state = 752 pdev_priv_obj->cur_chan_list[j].state; 753 pdev_priv_obj-> 754 cache_disable_chan_list[i].chan_flags = 755 pdev_priv_obj-> 756 cur_chan_list[j].chan_flags; 757 } 758 } 759 } 760 pdev_priv_obj->num_cache_channels = num_channels; 761 762 return QDF_STATUS_SUCCESS; 763 } 764 #endif /* CONFIG_CHAN_FREQ_API */ 765 #endif 766 767 #ifdef CONFIG_REG_CLIENT 768 769 QDF_STATUS reg_set_fcc_constraint(struct wlan_objmgr_pdev *pdev, 770 bool fcc_constraint) 771 { 772 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; 773 struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; 774 struct wlan_objmgr_psoc *psoc; 775 QDF_STATUS status; 776 777 pdev_priv_obj = reg_get_pdev_obj(pdev); 778 if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { 779 reg_err("pdev reg component is NULL"); 780 return QDF_STATUS_E_INVAL; 781 } 782 783 if (pdev_priv_obj->set_fcc_channel == fcc_constraint) { 784 reg_debug("same fcc_constraint %d", fcc_constraint); 785 return QDF_STATUS_SUCCESS; 786 } 787 788 reg_debug("set fcc_constraint: %d", fcc_constraint); 789 790 psoc = wlan_pdev_get_psoc(pdev); 791 if (!psoc) { 792 reg_err("psoc is NULL"); 793 return QDF_STATUS_E_INVAL; 794 } 795 796 psoc_priv_obj = reg_get_psoc_obj(psoc); 797 if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) { 798 reg_err("psoc reg component is NULL"); 799 return QDF_STATUS_E_INVAL; 800 } 801 802 psoc_priv_obj->set_fcc_channel = fcc_constraint; 803 pdev_priv_obj->set_fcc_channel = fcc_constraint; 804 805 reg_compute_pdev_current_chan_list(pdev_priv_obj); 806 807 status = reg_send_scheduler_msg_sb(psoc, pdev); 808 809 return status; 810 } 811 812 bool reg_get_fcc_constraint(struct wlan_objmgr_pdev *pdev, uint32_t freq) 813 { 814 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; 815 816 pdev_priv_obj = reg_get_pdev_obj(pdev); 817 if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { 818 reg_err("pdev reg component is NULL"); 819 return false; 820 } 821 822 if (freq != CHAN_12_CENT_FREQ && freq != CHAN_13_CENT_FREQ) 823 return false; 824 825 if (!pdev_priv_obj->set_fcc_channel) 826 return false; 827 828 return true; 829 } 830 831 #ifdef CONFIG_BAND_6GHZ 832 /** 833 * reg_is_afc_available() - check if the automated frequency control system is 834 * available, function will need to be updated once AFC is implemented 835 * @pdev: Pointer to pdev structure 836 * 837 * Return: false since the AFC system is not yet available 838 */ 839 static bool reg_is_afc_available(struct wlan_objmgr_pdev *pdev) 840 { 841 return false; 842 } 843 844 enum reg_6g_ap_type reg_decide_6g_ap_pwr_type(struct wlan_objmgr_pdev *pdev) 845 { 846 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; 847 enum reg_6g_ap_type ap_pwr_type = REG_INDOOR_AP; 848 849 pdev_priv_obj = reg_get_pdev_obj(pdev); 850 if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { 851 reg_err("pdev reg component is NULL"); 852 return REG_VERY_LOW_POWER_AP; 853 } 854 855 if (reg_is_afc_available(pdev)) { 856 ap_pwr_type = REG_STANDARD_POWER_AP; 857 } else if (pdev_priv_obj->indoor_chan_enabled) { 858 if (pdev_priv_obj->reg_rules.num_of_6g_ap_reg_rules[REG_INDOOR_AP]) 859 ap_pwr_type = REG_INDOOR_AP; 860 else 861 ap_pwr_type = REG_VERY_LOW_POWER_AP; 862 } else if (pdev_priv_obj->reg_rules.num_of_6g_ap_reg_rules[REG_VERY_LOW_POWER_AP]) { 863 ap_pwr_type = REG_VERY_LOW_POWER_AP; 864 } 865 reg_debug("indoor_chan_enabled %d ap_pwr_type %d", 866 pdev_priv_obj->indoor_chan_enabled, ap_pwr_type); 867 868 reg_set_ap_pwr_and_update_chan_list(pdev, ap_pwr_type); 869 870 return ap_pwr_type; 871 } 872 #endif /* CONFIG_BAND_6GHZ */ 873 874 #endif /* CONFIG_REG_CLIENT */ 875 876 /** 877 * reg_change_pdev_for_config() - Update user configuration in pdev private obj. 878 * @psoc: Pointer to global psoc structure. 879 * @object: Pointer to global pdev structure. 880 * @arg: Pointer to argument list. 881 */ 882 static void reg_change_pdev_for_config(struct wlan_objmgr_psoc *psoc, 883 void *object, void *arg) 884 { 885 struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)object; 886 struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; 887 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; 888 889 psoc_priv_obj = reg_get_psoc_obj(psoc); 890 if (!psoc_priv_obj) { 891 reg_err("psoc priv obj is NULL"); 892 return; 893 } 894 895 pdev_priv_obj = reg_get_pdev_obj(pdev); 896 897 if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { 898 reg_err("reg pdev private obj is NULL"); 899 return; 900 } 901 902 pdev_priv_obj->dfs_enabled = psoc_priv_obj->dfs_enabled; 903 pdev_priv_obj->indoor_chan_enabled = psoc_priv_obj->indoor_chan_enabled; 904 pdev_priv_obj->force_ssc_disable_indoor_channel = 905 psoc_priv_obj->force_ssc_disable_indoor_channel; 906 pdev_priv_obj->band_capability = psoc_priv_obj->band_capability; 907 pdev_priv_obj->sta_sap_scc_on_indoor_channel = 908 psoc_priv_obj->sta_sap_scc_on_indoor_channel; 909 910 reg_compute_pdev_current_chan_list(pdev_priv_obj); 911 912 reg_send_scheduler_msg_sb(psoc, pdev); 913 } 914 915 #if defined(CONFIG_BAND_6GHZ) && defined(CONFIG_AFC_SUPPORT) 916 static inline void 917 reg_set_afc_vars(struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj, 918 struct reg_config_vars *config_vars) 919 { 920 psoc_priv_obj->enable_6ghz_sp_pwrmode_supp = 921 config_vars->enable_6ghz_sp_pwrmode_supp; 922 psoc_priv_obj->afc_disable_timer_check = 923 config_vars->afc_disable_timer_check; 924 psoc_priv_obj->afc_disable_request_id_check = 925 config_vars->afc_disable_request_id_check; 926 psoc_priv_obj->is_afc_reg_noaction = 927 config_vars->is_afc_reg_noaction; 928 } 929 #else 930 static inline void 931 reg_set_afc_vars(struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj, 932 struct reg_config_vars *config_vars) 933 { 934 } 935 #endif 936 937 QDF_STATUS reg_set_config_vars(struct wlan_objmgr_psoc *psoc, 938 struct reg_config_vars config_vars) 939 { 940 struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; 941 QDF_STATUS status; 942 943 psoc_priv_obj = reg_get_psoc_obj(psoc); 944 if (!psoc_priv_obj) { 945 reg_err("psoc priv obj is NULL"); 946 return QDF_STATUS_E_FAILURE; 947 } 948 949 psoc_priv_obj->enable_11d_supp_original = 950 config_vars.enable_11d_support; 951 psoc_priv_obj->scan_11d_interval = config_vars.scan_11d_interval; 952 psoc_priv_obj->user_ctry_priority = config_vars.userspace_ctry_priority; 953 psoc_priv_obj->dfs_enabled = config_vars.dfs_enabled; 954 psoc_priv_obj->indoor_chan_enabled = config_vars.indoor_chan_enabled; 955 psoc_priv_obj->force_ssc_disable_indoor_channel = 956 config_vars.force_ssc_disable_indoor_channel; 957 psoc_priv_obj->band_capability = config_vars.band_capability; 958 psoc_priv_obj->restart_beaconing = config_vars.restart_beaconing; 959 psoc_priv_obj->enable_srd_chan_in_master_mode = 960 config_vars.enable_srd_chan_in_master_mode; 961 psoc_priv_obj->enable_11d_in_world_mode = 962 config_vars.enable_11d_in_world_mode; 963 psoc_priv_obj->enable_5dot9_ghz_chan_in_master_mode = 964 config_vars.enable_5dot9_ghz_chan_in_master_mode; 965 psoc_priv_obj->retain_nol_across_regdmn_update = 966 config_vars.retain_nol_across_regdmn_update; 967 reg_get_coex_unsafe_chan_nb_user_prefer(psoc_priv_obj, config_vars); 968 reg_get_coex_unsafe_chan_reg_disable(psoc_priv_obj, config_vars); 969 psoc_priv_obj->sta_sap_scc_on_indoor_channel = 970 config_vars.sta_sap_scc_on_indoor_channel; 971 reg_set_afc_vars(psoc_priv_obj, &config_vars); 972 973 status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_REGULATORY_SB_ID); 974 if (QDF_IS_STATUS_ERROR(status)) { 975 reg_err("error taking psoc ref cnt"); 976 return status; 977 } 978 status = wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP, 979 reg_change_pdev_for_config, 980 NULL, 1, WLAN_REGULATORY_SB_ID); 981 wlan_objmgr_psoc_release_ref(psoc, WLAN_REGULATORY_SB_ID); 982 983 return status; 984 } 985 986 void reg_program_mas_chan_list(struct wlan_objmgr_psoc *psoc, 987 struct regulatory_channel *reg_channels, 988 uint8_t *alpha2, 989 enum dfs_reg dfs_region) 990 { 991 struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; 992 QDF_STATUS status; 993 uint32_t count; 994 enum direction dir; 995 uint32_t phy_cnt; 996 997 psoc_priv_obj = reg_get_psoc_obj(psoc); 998 if (!psoc_priv_obj) { 999 reg_err("reg psoc private obj is NULL"); 1000 return; 1001 } 1002 1003 qdf_mem_copy(psoc_priv_obj->cur_country, alpha2, 1004 REG_ALPHA2_LEN); 1005 reg_debug("set cur_country %.2s", psoc_priv_obj->cur_country); 1006 for (count = 0; count < NUM_CHANNELS; count++) { 1007 reg_channels[count].chan_num = channel_map[count].chan_num; 1008 reg_channels[count].center_freq = 1009 channel_map[count].center_freq; 1010 reg_channels[count].nol_chan = false; 1011 } 1012 1013 for (phy_cnt = 0; phy_cnt < PSOC_MAX_PHY_REG_CAP; phy_cnt++) { 1014 qdf_mem_copy(psoc_priv_obj->mas_chan_params[phy_cnt]. 1015 mas_chan_list, reg_channels, 1016 NUM_CHANNELS * sizeof(struct regulatory_channel)); 1017 1018 psoc_priv_obj->mas_chan_params[phy_cnt].dfs_region = 1019 dfs_region; 1020 } 1021 1022 dir = SOUTHBOUND; 1023 status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_REGULATORY_SB_ID); 1024 if (QDF_IS_STATUS_ERROR(status)) { 1025 reg_err("error taking psoc ref cnt"); 1026 return; 1027 } 1028 status = wlan_objmgr_iterate_obj_list( 1029 psoc, WLAN_PDEV_OP, reg_propagate_mas_chan_list_to_pdev, 1030 &dir, 1, WLAN_REGULATORY_SB_ID); 1031 wlan_objmgr_psoc_release_ref(psoc, WLAN_REGULATORY_SB_ID); 1032 } 1033 1034 enum country_src reg_get_cc_and_src(struct wlan_objmgr_psoc *psoc, 1035 uint8_t *alpha2) 1036 { 1037 struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; 1038 1039 psoc_priv_obj = reg_get_psoc_obj(psoc); 1040 if (!psoc_priv_obj) { 1041 reg_err("reg psoc private obj is NULL"); 1042 return SOURCE_UNKNOWN; 1043 } 1044 1045 qdf_mem_copy(alpha2, psoc_priv_obj->cur_country, REG_ALPHA2_LEN + 1); 1046 1047 return psoc_priv_obj->cc_src; 1048 } 1049 1050 void reg_reset_ctry_pending_hints(struct wlan_regulatory_psoc_priv_obj 1051 *soc_reg) 1052 { 1053 uint8_t ctr; 1054 1055 if (!soc_reg->offload_enabled) 1056 return; 1057 1058 for (ctr = 0; ctr < PSOC_MAX_PHY_REG_CAP; ctr++) { 1059 soc_reg->new_user_ctry_pending[ctr] = false; 1060 soc_reg->new_init_ctry_pending[ctr] = false; 1061 soc_reg->new_11d_ctry_pending[ctr] = false; 1062 soc_reg->world_country_pending[ctr] = false; 1063 } 1064 } 1065 1066 QDF_STATUS reg_set_curr_country(struct wlan_regulatory_psoc_priv_obj *soc_reg, 1067 struct cur_regulatory_info *regulat_info, 1068 struct wlan_lmac_if_reg_tx_ops *tx_ops) 1069 { 1070 struct wlan_objmgr_psoc *psoc = regulat_info->psoc; 1071 struct wlan_objmgr_pdev *pdev; 1072 uint8_t pdev_id; 1073 uint8_t phy_id; 1074 uint8_t phy_num; 1075 struct set_country country_code; 1076 QDF_STATUS status; 1077 1078 /* 1079 * During SSR/WLAN restart ignore master channel list 1080 * for all events and in the last event handling if 1081 * current country and default country is different, send the last 1082 * configured (soc_reg->cur_country) country. 1083 */ 1084 if ((regulat_info->num_phy != regulat_info->phy_id + 1) || 1085 (!qdf_mem_cmp(soc_reg->cur_country, regulat_info->alpha2, 1086 REG_ALPHA2_LEN))) 1087 return QDF_STATUS_SUCCESS; 1088 1089 /* 1090 * Need firmware to send channel list event 1091 * for all phys. Therefore set pdev_id to 0xFF. 1092 */ 1093 pdev_id = WMI_HOST_PDEV_ID_SOC; 1094 for (phy_num = 0; phy_num < regulat_info->num_phy; phy_num++) { 1095 if (soc_reg->cc_src == SOURCE_USERSPACE) 1096 soc_reg->new_user_ctry_pending[phy_num] = true; 1097 else if (soc_reg->cc_src == SOURCE_11D) 1098 soc_reg->new_11d_ctry_pending[phy_num] = true; 1099 else 1100 soc_reg->world_country_pending[phy_num] = true; 1101 } 1102 1103 qdf_mem_zero(&country_code, sizeof(country_code)); 1104 qdf_mem_copy(country_code.country, soc_reg->cur_country, 1105 sizeof(soc_reg->cur_country)); 1106 country_code.pdev_id = pdev_id; 1107 1108 if (soc_reg->offload_enabled) { 1109 if (!tx_ops || !tx_ops->set_country_code) { 1110 reg_err("No regulatory tx_ops"); 1111 status = QDF_STATUS_E_FAULT; 1112 goto error; 1113 } 1114 status = tx_ops->set_country_code(psoc, &country_code); 1115 if (QDF_IS_STATUS_ERROR(status)) { 1116 reg_err("Failed to send country code to fw"); 1117 goto error; 1118 } 1119 } else { 1120 phy_id = regulat_info->phy_id; 1121 if (tx_ops->get_pdev_id_from_phy_id) 1122 tx_ops->get_pdev_id_from_phy_id(psoc, phy_id, &pdev_id); 1123 else 1124 pdev_id = phy_id; 1125 1126 pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id, 1127 WLAN_REGULATORY_NB_ID); 1128 status = reg_set_non_offload_country(pdev, &country_code); 1129 wlan_objmgr_pdev_release_ref(pdev, WLAN_REGULATORY_NB_ID); 1130 if (QDF_IS_STATUS_ERROR(status)) { 1131 reg_err("Failed to set country code"); 1132 goto error; 1133 } 1134 } 1135 1136 reg_debug("Target CC: %.2s, Restore to Previous CC: %.2s", 1137 regulat_info->alpha2, soc_reg->cur_country); 1138 1139 return status; 1140 1141 error: 1142 reg_reset_ctry_pending_hints(soc_reg); 1143 1144 return status; 1145 } 1146 1147 bool reg_ignore_default_country(struct wlan_regulatory_psoc_priv_obj *soc_reg, 1148 struct cur_regulatory_info *regulat_info) 1149 { 1150 uint8_t phy_num; 1151 1152 if (soc_reg->cc_src == SOURCE_UNKNOWN) 1153 return false; 1154 1155 phy_num = regulat_info->phy_id; 1156 if (soc_reg->new_user_ctry_pending[phy_num] || 1157 soc_reg->new_init_ctry_pending[phy_num] || 1158 soc_reg->new_11d_ctry_pending[phy_num] || 1159 soc_reg->world_country_pending[phy_num]) 1160 return false; 1161 1162 return true; 1163 } 1164