1 /* 2 * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2024 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: wlan_hdd_regulatory.c 22 * 23 * hdd regulatory implementation 24 */ 25 26 #include "qdf_types.h" 27 #include "qdf_trace.h" 28 #include "wlan_hdd_main.h" 29 #include <wlan_osif_priv.h> 30 #include "wlan_hdd_regulatory.h" 31 #include <wlan_reg_ucfg_api.h> 32 #include "cds_regdomain.h" 33 #include "cds_utils.h" 34 #include "pld_common.h" 35 #include <net/cfg80211.h> 36 #include "wlan_policy_mgr_ucfg.h" 37 #include "sap_api.h" 38 #include "wlan_hdd_hostapd.h" 39 #include "osif_psoc_sync.h" 40 #include "wlan_osif_features.h" 41 #include "wlan_p2p_ucfg_api.h" 42 43 #define REG_RULE_2412_2462 REG_RULE(2412-10, 2462+10, 40, 0, 20, 0) 44 45 #define REG_RULE_2467_2472 REG_RULE(2467-10, 2472+10, 40, 0, 20, \ 46 NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) 47 48 #define REG_RULE_2484 REG_RULE(2484-10, 2484+10, 20, 0, 20, \ 49 NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS | \ 50 NL80211_RRF_NO_OFDM) 51 52 #define REG_RULE_5180_5320 REG_RULE(5180-10, 5320+10, 160, 0, 20, \ 53 NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) 54 55 #define REG_RULE_5500_5720 REG_RULE(5500-10, 5720+10, 160, 0, 20, \ 56 NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) 57 58 #define REG_RULE_5745_5925 REG_RULE(5745-10, 5925+10, 80, 0, 20, \ 59 NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) 60 61 static bool init_by_driver; 62 static bool init_by_reg_core; 63 64 struct regulatory_channel reg_channels[NUM_CHANNELS]; 65 66 static const struct ieee80211_regdomain 67 hdd_world_regrules_60_61_62 = { 68 .n_reg_rules = 6, 69 .alpha2 = "00", 70 .reg_rules = { 71 REG_RULE_2412_2462, 72 REG_RULE_2467_2472, 73 REG_RULE_2484, 74 REG_RULE_5180_5320, 75 REG_RULE_5500_5720, 76 REG_RULE_5745_5925, 77 } 78 }; 79 80 static const struct ieee80211_regdomain 81 hdd_world_regrules_63_65 = { 82 .n_reg_rules = 4, 83 .alpha2 = "00", 84 .reg_rules = { 85 REG_RULE_2412_2462, 86 REG_RULE_2467_2472, 87 REG_RULE_5180_5320, 88 REG_RULE_5745_5925, 89 } 90 }; 91 92 static const struct ieee80211_regdomain 93 hdd_world_regrules_64 = { 94 .n_reg_rules = 3, 95 .alpha2 = "00", 96 .reg_rules = { 97 REG_RULE_2412_2462, 98 REG_RULE_5180_5320, 99 REG_RULE_5745_5925, 100 } 101 }; 102 103 static const struct ieee80211_regdomain 104 hdd_world_regrules_66_69 = { 105 .n_reg_rules = 4, 106 .alpha2 = "00", 107 .reg_rules = { 108 REG_RULE_2412_2462, 109 REG_RULE_5180_5320, 110 REG_RULE_5500_5720, 111 REG_RULE_5745_5925, 112 } 113 }; 114 115 static const struct ieee80211_regdomain 116 hdd_world_regrules_67_68_6A_6C = { 117 .n_reg_rules = 5, 118 .alpha2 = "00", 119 .reg_rules = { 120 REG_RULE_2412_2462, 121 REG_RULE_2467_2472, 122 REG_RULE_5180_5320, 123 REG_RULE_5500_5720, 124 REG_RULE_5745_5925, 125 } 126 }; 127 128 #define COUNTRY_CHANGE_WORK_RESCHED_WAIT_TIME 30 129 /** 130 * hdd_get_world_regrules() - get the appropriate world regrules 131 * @reg: regulatory data 132 * 133 * Return: regulatory rules ptr 134 */ 135 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)) 136 static const struct ieee80211_regdomain *hdd_get_world_regrules( 137 struct regulatory *reg) 138 { 139 struct reg_dmn_pair *regpair = 140 (struct reg_dmn_pair *)reg->regpair; 141 142 switch (regpair->reg_dmn_pair) { 143 case 0x60: 144 case 0x61: 145 case 0x62: 146 return &hdd_world_regrules_60_61_62; 147 case 0x63: 148 case 0x65: 149 return &hdd_world_regrules_63_65; 150 case 0x64: 151 return &hdd_world_regrules_64; 152 case 0x66: 153 case 0x69: 154 return &hdd_world_regrules_66_69; 155 case 0x67: 156 case 0x68: 157 case 0x6A: 158 case 0x6C: 159 return &hdd_world_regrules_67_68_6A_6C; 160 default: 161 hdd_warn("invalid world mode in BDF"); 162 return &hdd_world_regrules_60_61_62; 163 } 164 } 165 166 /** 167 * hdd_is_world_regdomain() - whether world regdomain 168 * @reg_domain: integer regulatory domain 169 * 170 * Return: bool 171 */ 172 static bool hdd_is_world_regdomain(uint32_t reg_domain) 173 { 174 uint32_t temp_regd = reg_domain & ~WORLD_ROAMING_FLAG; 175 176 return ((temp_regd & CTRY_FLAG) != CTRY_FLAG) && 177 ((temp_regd & WORLD_ROAMING_MASK) == 178 WORLD_ROAMING_PREFIX); 179 } 180 181 /** 182 * hdd_update_regulatory_info() - update regulatory info 183 * @hdd_ctx: hdd context 184 * 185 * Return: Error Code 186 */ 187 static int hdd_update_regulatory_info(struct hdd_context *hdd_ctx) 188 { 189 uint32_t country_code; 190 191 country_code = cds_get_country_from_alpha2(hdd_ctx->reg.alpha2); 192 193 hdd_ctx->reg.reg_domain = CTRY_FLAG; 194 hdd_ctx->reg.reg_domain |= country_code; 195 196 return cds_fill_some_regulatory_info(&hdd_ctx->reg); 197 198 } 199 #endif 200 201 /** 202 * hdd_reset_global_reg_params - Reset global static reg params 203 * 204 * This function is helpful in static driver to reset 205 * the global params. 206 * 207 * Return: void 208 */ 209 void hdd_reset_global_reg_params(void) 210 { 211 init_by_driver = false; 212 init_by_reg_core = false; 213 } 214 215 /** 216 * hdd_update_coex_unsafe_chan_nb_user_prefer() - update coex unsafe 217 * nb prefer framework 218 * @hdd_ctx: hdd context 219 * @config_vars: reg config 220 * 221 * Return: void 222 */ 223 #ifdef FEATURE_WLAN_CH_AVOID_EXT 224 static inline 225 void hdd_update_coex_unsafe_chan_nb_user_prefer( 226 struct hdd_context *hdd_ctx, 227 struct reg_config_vars *config_vars) 228 { 229 config_vars->coex_unsafe_chan_nb_user_prefer = 230 ucfg_mlme_get_coex_unsafe_chan_nb_user_prefer( 231 hdd_ctx->psoc); 232 } 233 234 static inline 235 void hdd_update_coex_unsafe_chan_reg_disable( 236 struct hdd_context *hdd_ctx, 237 struct reg_config_vars *config_vars) 238 { 239 config_vars->coex_unsafe_chan_reg_disable = 240 ucfg_mlme_get_coex_unsafe_chan_reg_disable( 241 hdd_ctx->psoc); 242 } 243 #else 244 static inline 245 void hdd_update_coex_unsafe_chan_nb_user_prefer( 246 struct hdd_context *hdd_ctx, 247 struct reg_config_vars *config_vars) 248 { 249 } 250 251 static inline 252 void hdd_update_coex_unsafe_chan_reg_disable( 253 struct hdd_context *hdd_ctx, 254 struct reg_config_vars *config_vars) 255 { 256 } 257 #endif 258 259 #if defined(CONFIG_AFC_SUPPORT) && defined(CONFIG_BAND_6GHZ) 260 static inline 261 void hdd_update_afc_config(struct hdd_context *hdd_ctx, 262 struct reg_config_vars *config_vars) 263 { 264 bool enable_6ghz_sp_pwrmode_supp = false; 265 bool afc_disable_timer_check = false; 266 bool afc_disable_request_id_check = false; 267 bool is_afc_reg_noaction = false; 268 269 ucfg_mlme_get_enable_6ghz_sp_mode_support(hdd_ctx->psoc, 270 &enable_6ghz_sp_pwrmode_supp); 271 config_vars->enable_6ghz_sp_pwrmode_supp = enable_6ghz_sp_pwrmode_supp; 272 ucfg_mlme_get_afc_disable_timer_check(hdd_ctx->psoc, 273 &afc_disable_timer_check); 274 config_vars->afc_disable_timer_check = afc_disable_timer_check; 275 ucfg_mlme_get_afc_disable_request_id_check( 276 hdd_ctx->psoc, &afc_disable_request_id_check); 277 config_vars->afc_disable_request_id_check = 278 afc_disable_request_id_check; 279 ucfg_mlme_get_afc_reg_noaction(hdd_ctx->psoc, 280 &is_afc_reg_noaction); 281 config_vars->is_afc_reg_noaction = is_afc_reg_noaction; 282 } 283 #else 284 static inline 285 void hdd_update_afc_config(struct hdd_context *hdd_ctx, 286 struct reg_config_vars *config_vars) 287 { 288 } 289 #endif 290 291 static void reg_program_config_vars(struct hdd_context *hdd_ctx, 292 struct reg_config_vars *config_vars) 293 { 294 uint8_t indoor_chnl_marking = 0; 295 uint32_t band_capability = 0, scan_11d_interval = 0; 296 bool indoor_chan_enabled = false; 297 uint32_t restart_beaconing = 0; 298 uint8_t enable_srd_chan; 299 bool enable_5dot9_ghz_chan; 300 QDF_STATUS status; 301 bool country_priority = 0; 302 bool value = false; 303 bool enable_dfs_scan = true; 304 305 status = ucfg_mlme_get_band_capability(hdd_ctx->psoc, &band_capability); 306 if (QDF_IS_STATUS_ERROR(status)) 307 hdd_err("Failed to get MLME band cap, defaulting to BAND_ALL"); 308 309 status = ucfg_policy_mgr_get_indoor_chnl_marking(hdd_ctx->psoc, 310 &indoor_chnl_marking); 311 if (QDF_STATUS_SUCCESS != status) 312 hdd_err("can't get indoor channel marking, using default"); 313 314 status = ucfg_mlme_is_11d_enabled(hdd_ctx->psoc, &value); 315 if (!QDF_IS_STATUS_SUCCESS(status)) 316 hdd_err("Invalid 11d_enable flag"); 317 config_vars->enable_11d_support = value; 318 319 ucfg_mlme_get_nol_across_regdmn(hdd_ctx->psoc, &value); 320 config_vars->retain_nol_across_regdmn_update = value; 321 322 ucfg_mlme_get_scan_11d_interval(hdd_ctx->psoc, &scan_11d_interval); 323 config_vars->scan_11d_interval = scan_11d_interval; 324 325 ucfg_mlme_get_sap_country_priority(hdd_ctx->psoc, 326 &country_priority); 327 config_vars->userspace_ctry_priority = country_priority; 328 329 ucfg_scan_cfg_get_dfs_chan_scan_allowed(hdd_ctx->psoc, 330 &enable_dfs_scan); 331 332 config_vars->dfs_enabled = enable_dfs_scan; 333 334 ucfg_mlme_get_indoor_channel_support(hdd_ctx->psoc, 335 &indoor_chan_enabled); 336 config_vars->indoor_chan_enabled = indoor_chan_enabled; 337 338 config_vars->force_ssc_disable_indoor_channel = indoor_chnl_marking; 339 config_vars->band_capability = band_capability; 340 341 ucfg_mlme_get_restart_beaconing_on_ch_avoid(hdd_ctx->psoc, 342 &restart_beaconing); 343 config_vars->restart_beaconing = restart_beaconing; 344 345 ucfg_mlme_get_etsi_srd_chan_in_master_mode(hdd_ctx->psoc, 346 &enable_srd_chan); 347 config_vars->enable_srd_chan_in_master_mode = enable_srd_chan; 348 349 ucfg_mlme_get_11d_in_world_mode(hdd_ctx->psoc, 350 &config_vars->enable_11d_in_world_mode); 351 352 ucfg_mlme_get_5dot9_ghz_chan_in_master_mode(hdd_ctx->psoc, 353 &enable_5dot9_ghz_chan); 354 config_vars->enable_5dot9_ghz_chan_in_master_mode = 355 enable_5dot9_ghz_chan; 356 hdd_update_coex_unsafe_chan_nb_user_prefer(hdd_ctx, config_vars); 357 hdd_update_coex_unsafe_chan_reg_disable(hdd_ctx, config_vars); 358 hdd_update_afc_config(hdd_ctx, config_vars); 359 config_vars->sta_sap_scc_on_indoor_channel = 360 ucfg_policy_mgr_get_sta_sap_scc_on_indoor_chnl(hdd_ctx->psoc); 361 config_vars->p2p_indoor_ch_support = 362 ucfg_p2p_get_indoor_ch_support(hdd_ctx->psoc); 363 } 364 365 /** 366 * hdd_regulatory_wiphy_init() - regulatory wiphy init 367 * @hdd_ctx: hdd context 368 * @reg: regulatory data 369 * @wiphy: wiphy structure 370 * 371 * Return: void 372 */ 373 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) 374 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(WITH_BACKPORTS) 375 static void hdd_regulatory_wiphy_init(struct hdd_context *hdd_ctx, 376 struct regulatory *reg, 377 struct wiphy *wiphy) 378 { 379 const struct ieee80211_regdomain *reg_rules; 380 int chan_num; 381 struct ieee80211_channel *chan; 382 383 if (hdd_is_world_regdomain(reg->reg_domain)) { 384 reg_rules = hdd_get_world_regrules(reg); 385 wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; 386 } else { 387 wiphy->regulatory_flags |= REGULATORY_STRICT_REG; 388 reg_rules = &hdd_world_regrules_60_61_62; 389 } 390 391 /* 392 * save the original driver regulatory flags 393 */ 394 hdd_ctx->reg.reg_flags = wiphy->regulatory_flags; 395 wiphy_apply_custom_regulatory(wiphy, reg_rules); 396 397 /* 398 * disable 2.4 Ghz channels that dont have 20 mhz bw 399 */ 400 for (chan_num = 0; 401 chan_num < wiphy->bands[HDD_NL80211_BAND_2GHZ]->n_channels; 402 chan_num++) { 403 chan = &(wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels[chan_num]); 404 if (chan->flags & IEEE80211_CHAN_NO_20MHZ) 405 chan->flags |= IEEE80211_CHAN_DISABLED; 406 } 407 408 /* 409 * restore the driver regulatory flags since 410 * wiphy_apply_custom_regulatory may have 411 * changed them 412 */ 413 wiphy->regulatory_flags = hdd_ctx->reg.reg_flags; 414 415 } 416 #else 417 static void hdd_regulatory_wiphy_init(struct hdd_context *hdd_ctx, 418 struct regulatory *reg, 419 struct wiphy *wiphy) 420 { 421 const struct ieee80211_regdomain *reg_rules; 422 423 if (hdd_is_world_regdomain(reg->reg_domain)) { 424 reg_rules = hdd_get_world_regrules(reg); 425 wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; 426 } else { 427 wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY; 428 reg_rules = &hdd_world_regrules_60_61_62; 429 } 430 431 /* 432 * save the original driver regulatory flags 433 */ 434 hdd_ctx->reg.reg_flags = wiphy->flags; 435 wiphy_apply_custom_regulatory(wiphy, reg_rules); 436 437 /* 438 * restore the driver regulatory flags since 439 * wiphy_apply_custom_regulatory may have 440 * changed them 441 */ 442 wiphy->flags = hdd_ctx->reg.reg_flags; 443 444 } 445 #endif 446 447 /** 448 * is_wiphy_custom_regulatory() - is custom regulatory defined 449 * @wiphy: wiphy 450 * 451 * Return: int 452 */ 453 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) 454 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(WITH_BACKPORTS) 455 static int is_wiphy_custom_regulatory(struct wiphy *wiphy) 456 { 457 458 return wiphy->regulatory_flags & REGULATORY_CUSTOM_REG; 459 } 460 #else 461 static int is_wiphy_custom_regulatory(struct wiphy *wiphy) 462 { 463 return wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY; 464 } 465 #endif 466 467 /** 468 * hdd_modify_wiphy() - modify wiphy 469 * @wiphy: wiphy 470 * @chan: channel structure 471 * 472 * Return: void 473 */ 474 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)) 475 static void hdd_modify_wiphy(struct wiphy *wiphy, 476 struct ieee80211_channel *chan) 477 { 478 const struct ieee80211_reg_rule *reg_rule; 479 480 if (is_wiphy_custom_regulatory(wiphy)) { 481 reg_rule = freq_reg_info(wiphy, MHZ_TO_KHZ(chan->center_freq)); 482 if (!IS_ERR(reg_rule)) { 483 chan->flags &= ~IEEE80211_CHAN_DISABLED; 484 485 if (!(reg_rule->flags & NL80211_RRF_DFS)) { 486 hdd_debug("Remove dfs restriction for %u", 487 chan->center_freq); 488 chan->flags &= ~IEEE80211_CHAN_RADAR; 489 } 490 491 if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) { 492 hdd_debug("Remove passive restriction for %u", 493 chan->center_freq); 494 chan->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; 495 } 496 497 if (!(reg_rule->flags & NL80211_RRF_NO_IBSS)) { 498 hdd_debug("Remove no ibss restriction for %u", 499 chan->center_freq); 500 chan->flags &= ~IEEE80211_CHAN_NO_IBSS; 501 } 502 503 chan->max_power = 504 MBM_TO_DBM(reg_rule->power_rule.max_eirp); 505 } 506 } 507 } 508 #endif 509 510 /** 511 * hdd_set_dfs_region() - set the dfs_region 512 * @hdd_ctx: HDD context 513 * @dfs_reg: the dfs_region to set 514 * 515 * Return: void 516 */ 517 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) 518 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(WITH_BACKPORTS) 519 static void hdd_set_dfs_region(struct hdd_context *hdd_ctx, 520 enum dfs_reg dfs_reg) 521 { 522 wlan_reg_set_dfs_region(hdd_ctx->pdev, dfs_reg); 523 } 524 #endif 525 526 /** 527 * hdd_process_regulatory_data() - process regulatory data 528 * @hdd_ctx: hdd context 529 * @wiphy: wiphy 530 * @reset: whether to reset channel data 531 * 532 * Return: void 533 */ 534 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)) 535 static void hdd_process_regulatory_data(struct hdd_context *hdd_ctx, 536 struct wiphy *wiphy, 537 bool reset) 538 { 539 int band_num; 540 int chan_num; 541 enum channel_enum chan_enum = CHAN_ENUM_1; 542 struct ieee80211_channel *wiphy_chan, *wiphy_chan_144 = NULL; 543 struct regulatory_channel *cds_chan; 544 uint8_t band_capability, indoor_chnl_marking = 0; 545 bool indoor, sta_sap_con_on_indoor; 546 QDF_STATUS status; 547 548 band_capability = hdd_ctx->curr_band; 549 550 status = ucfg_policy_mgr_get_indoor_chnl_marking(hdd_ctx->psoc, 551 &indoor_chnl_marking); 552 553 if (QDF_STATUS_SUCCESS != status) 554 hdd_err("can't get indoor channel marking, using default"); 555 556 sta_sap_con_on_indoor = 557 ucfg_policy_mgr_get_sta_sap_scc_on_indoor_chnl(hdd_ctx->psoc); 558 559 for (band_num = 0; band_num < HDD_NUM_NL80211_BANDS; band_num++) { 560 561 if (!wiphy->bands[band_num]) 562 continue; 563 564 for (chan_num = 0; 565 chan_num < wiphy->bands[band_num]->n_channels && 566 chan_enum < NUM_CHANNELS; 567 chan_num++) { 568 wiphy_chan = 569 &(wiphy->bands[band_num]->channels[chan_num]); 570 cds_chan = &(reg_channels[chan_enum]); 571 cds_chan->chan_flags = 0; 572 if (CHAN_ENUM_144 == chan_enum) 573 wiphy_chan_144 = wiphy_chan; 574 575 chan_enum++; 576 577 if (!reset) 578 hdd_modify_wiphy(wiphy, wiphy_chan); 579 580 if (indoor_chnl_marking && 581 (wiphy_chan->flags & IEEE80211_CHAN_INDOOR_ONLY)) 582 cds_chan->chan_flags |= 583 REGULATORY_CHAN_INDOOR_ONLY; 584 585 if (wiphy_chan->flags & IEEE80211_CHAN_DISABLED) { 586 cds_chan->state = CHANNEL_STATE_DISABLE; 587 cds_chan->chan_flags |= 588 REGULATORY_CHAN_DISABLED; 589 } else if (wiphy_chan->flags & 590 (IEEE80211_CHAN_RADAR | 591 IEEE80211_CHAN_PASSIVE_SCAN)) { 592 cds_chan->state = CHANNEL_STATE_DFS; 593 if (wiphy_chan->flags & IEEE80211_CHAN_RADAR) 594 cds_chan->chan_flags |= 595 REGULATORY_CHAN_RADAR; 596 if (wiphy_chan->flags & 597 IEEE80211_CHAN_PASSIVE_SCAN) 598 cds_chan->chan_flags |= 599 REGULATORY_CHAN_NO_IR; 600 } else if (wiphy_chan->flags & 601 IEEE80211_CHAN_INDOOR_ONLY) { 602 cds_chan->chan_flags |= 603 REGULATORY_CHAN_INDOOR_ONLY; 604 605 ucfg_mlme_get_indoor_channel_support( 606 hdd_ctx->psoc, 607 &indoor); 608 if (!indoor) { 609 cds_chan->state = CHANNEL_STATE_DFS; 610 wiphy_chan->flags |= 611 IEEE80211_CHAN_PASSIVE_SCAN; 612 if (!sta_sap_con_on_indoor) 613 cds_chan->chan_flags |= 614 REGULATORY_CHAN_NO_IR; 615 } else 616 cds_chan->state = CHANNEL_STATE_ENABLE; 617 } else 618 cds_chan->state = CHANNEL_STATE_ENABLE; 619 cds_chan->tx_power = wiphy_chan->max_power; 620 if (wiphy_chan->flags & IEEE80211_CHAN_NO_10MHZ) 621 cds_chan->max_bw = 5; 622 else if (wiphy_chan->flags & IEEE80211_CHAN_NO_20MHZ) 623 cds_chan->max_bw = 10; 624 /* 625 * IEEE80211_CHAN_NO_HT40 is defined as 0x30 in kernel 626 * 4th BIT representing IEEE80211_CHAN_NO_HT40PLUS 627 * 5th BIT representing IEEE80211_CHAN_NO_HT40MINUS 628 * 629 * In order to claim no 40Mhz support value of 630 * wiphy_chan->flags needs to be 0x30. 631 * 0x20 and 0x10 values shows that either HT40+ or 632 * HT40- is not supported based on BIT set but they 633 * can support 40Mhz Operation. 634 */ 635 else if ((wiphy_chan->flags & IEEE80211_CHAN_NO_HT40) == 636 IEEE80211_CHAN_NO_HT40) 637 cds_chan->max_bw = 20; 638 else if (wiphy_chan->flags & IEEE80211_CHAN_NO_80MHZ) 639 cds_chan->max_bw = 40; 640 else if (wiphy_chan->flags & IEEE80211_CHAN_NO_160MHZ) 641 cds_chan->max_bw = 80; 642 else 643 cds_chan->max_bw = 160; 644 } 645 } 646 647 if (0 == (hdd_ctx->reg.eeprom_rd_ext & 648 (1 << WMI_REG_EXT_FCC_CH_144))) { 649 cds_chan = &(reg_channels[CHAN_ENUM_144]); 650 cds_chan->state = CHANNEL_STATE_DISABLE; 651 if (wiphy_chan_144) 652 wiphy_chan_144->flags |= IEEE80211_CHAN_DISABLED; 653 } 654 655 wlan_hdd_cfg80211_update_band(hdd_ctx, wiphy, band_capability); 656 } 657 658 /** 659 * hdd_regulatory_init_no_offload() - regulatory init 660 * @hdd_ctx: hdd context 661 * @wiphy: wiphy 662 * 663 * Return: int 664 */ 665 static int hdd_regulatory_init_no_offload(struct hdd_context *hdd_ctx, 666 struct wiphy *wiphy) 667 { 668 int ret_val; 669 struct regulatory *reg_info; 670 enum dfs_reg dfs_reg; 671 struct reg_config_vars config_vars; 672 673 reg_info = &hdd_ctx->reg; 674 675 ret_val = cds_fill_some_regulatory_info(reg_info); 676 if (ret_val) { 677 hdd_err("incorrect BDF regulatory data"); 678 return ret_val; 679 } 680 681 hdd_set_dfs_region(hdd_ctx, DFS_FCC_REGION); 682 683 hdd_regulatory_wiphy_init(hdd_ctx, reg_info, wiphy); 684 685 hdd_process_regulatory_data(hdd_ctx, wiphy, true); 686 687 reg_info->cc_src = SOURCE_DRIVER; 688 689 ucfg_reg_set_default_country(hdd_ctx->psoc, reg_info->alpha2); 690 691 cds_fill_and_send_ctl_to_fw(reg_info); 692 693 wlan_reg_get_dfs_region(hdd_ctx->pdev, &dfs_reg); 694 695 reg_program_config_vars(hdd_ctx, &config_vars); 696 ucfg_reg_set_config_vars(hdd_ctx->psoc, config_vars); 697 ucfg_reg_program_mas_chan_list(hdd_ctx->psoc, 698 reg_channels, 699 hdd_ctx->reg.alpha2, 700 dfs_reg); 701 702 return 0; 703 } 704 #endif 705 706 /** 707 * hdd_modify_indoor_channel_state_flags() - modify wiphy flags and cds state 708 * @hdd_ctx: HDD context 709 * @wiphy_chan: wiphy channel number 710 * @cds_chan: cds channel structure 711 * @chan_enum: enumerated value of the channel 712 * @chan_num: channel number 713 * @disable: Disable/enable the flags 714 * 715 * Modify wiphy flags and cds state if channel is indoor. 716 * 717 * Return: void 718 */ 719 void hdd_modify_indoor_channel_state_flags( 720 struct hdd_context *hdd_ctx, 721 struct ieee80211_channel *wiphy_chan, 722 struct regulatory_channel *cds_chan, 723 enum channel_enum chan_enum, int chan_num, bool disable) 724 { 725 bool indoor_support; 726 727 ucfg_mlme_get_indoor_channel_support(hdd_ctx->psoc, &indoor_support); 728 729 /* Mark indoor channel to disable in wiphy and cds */ 730 if (disable) { 731 if (wiphy_chan->flags & IEEE80211_CHAN_INDOOR_ONLY) { 732 wiphy_chan->flags |= 733 IEEE80211_CHAN_DISABLED; 734 hdd_info("Mark indoor channel %d as disable", 735 cds_chan->center_freq); 736 cds_chan->state = 737 CHANNEL_STATE_DISABLE; 738 } 739 } else { 740 if (wiphy_chan->flags & IEEE80211_CHAN_INDOOR_ONLY) { 741 wiphy_chan->flags &= 742 ~IEEE80211_CHAN_DISABLED; 743 /* 744 * Indoor channels may be marked as dfs / enable 745 * during regulatory processing 746 */ 747 if ((wiphy_chan->flags & 748 (IEEE80211_CHAN_RADAR | 749 IEEE80211_CHAN_PASSIVE_SCAN)) || 750 ((indoor_support == false) && 751 (wiphy_chan->flags & 752 IEEE80211_CHAN_INDOOR_ONLY))) 753 cds_chan->state = 754 CHANNEL_STATE_DFS; 755 else 756 cds_chan->state = 757 CHANNEL_STATE_ENABLE; 758 hdd_debug("Mark indoor channel %d as cds_chan state %d", 759 cds_chan->chan_num, cds_chan->state); 760 } 761 } 762 763 } 764 765 void hdd_update_indoor_channel(struct hdd_context *hdd_ctx, 766 bool disable) 767 { 768 int band_num; 769 int chan_num; 770 enum channel_enum chan_enum = CHAN_ENUM_2412; 771 struct ieee80211_channel *wiphy_chan, *wiphy_chan_144 = NULL; 772 struct regulatory_channel *cds_chan; 773 uint8_t band_capability; 774 struct wiphy *wiphy = hdd_ctx->wiphy; 775 776 hdd_enter(); 777 hdd_debug("mark indoor channel disable: %d", disable); 778 779 band_capability = hdd_ctx->curr_band; 780 for (band_num = 0; band_num < HDD_NUM_NL80211_BANDS; band_num++) { 781 782 if (!wiphy->bands[band_num]) 783 continue; 784 785 for (chan_num = 0; 786 chan_num < wiphy->bands[band_num]->n_channels && 787 chan_enum < NUM_CHANNELS; 788 chan_num++) { 789 790 wiphy_chan = 791 &(wiphy->bands[band_num]->channels[chan_num]); 792 cds_chan = &(reg_channels[chan_enum]); 793 if (chan_enum == CHAN_ENUM_5720) 794 wiphy_chan_144 = wiphy_chan; 795 796 chan_enum++; 797 hdd_modify_indoor_channel_state_flags(hdd_ctx, 798 wiphy_chan, cds_chan, 799 chan_enum, chan_num, disable); 800 } 801 } 802 803 /* Notify the regulatory domain to update the channel list */ 804 if (QDF_IS_STATUS_ERROR(ucfg_reg_notify_sap_event(hdd_ctx->pdev, 805 disable))) { 806 hdd_err("Failed to notify sap event"); 807 } 808 hdd_exit(); 809 810 } 811 812 /** 813 * hdd_program_country_code() - process channel information from country code 814 * @hdd_ctx: hddc context 815 * 816 * Return: void 817 */ 818 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) 819 void hdd_program_country_code(struct hdd_context *hdd_ctx) 820 { 821 } 822 #else 823 void hdd_program_country_code(struct hdd_context *hdd_ctx) 824 { 825 struct wiphy *wiphy = hdd_ctx->wiphy; 826 uint8_t *country_alpha2 = hdd_ctx->reg.alpha2; 827 828 if (!init_by_reg_core && !init_by_driver) { 829 init_by_driver = true; 830 if (('0' != country_alpha2[0]) || 831 ('0' != country_alpha2[1])) 832 regulatory_hint(wiphy, country_alpha2); 833 } 834 } 835 #endif 836 837 void hdd_reg_wait_for_country_change(struct hdd_context *hdd_ctx) 838 { 839 qdf_mutex_acquire(&hdd_ctx->regulatory_status_lock); 840 if (hdd_ctx->is_regulatory_update_in_progress) { 841 qdf_mutex_release(&hdd_ctx->regulatory_status_lock); 842 hdd_debug("waiting for channel list to update"); 843 qdf_wait_for_event_completion(&hdd_ctx->regulatory_update_event, 844 CHANNEL_LIST_UPDATE_TIMEOUT); 845 /* In case of set country failure in FW, response never comes 846 * so wait the full timeout, then set in_progress to false. 847 * If the response comes back, in_progress will already be set 848 * to false anyways. 849 */ 850 qdf_mutex_acquire(&hdd_ctx->regulatory_status_lock); 851 hdd_ctx->is_regulatory_update_in_progress = false; 852 qdf_mutex_release(&hdd_ctx->regulatory_status_lock); 853 } else { 854 qdf_mutex_release(&hdd_ctx->regulatory_status_lock); 855 } 856 } 857 858 int hdd_reg_set_country(struct hdd_context *hdd_ctx, char *country_code) 859 { 860 QDF_STATUS status; 861 uint8_t cc[REG_ALPHA2_LEN + 1]; 862 uint8_t alpha2[REG_ALPHA2_LEN + 1]; 863 enum country_src cc_src; 864 865 if (!country_code) { 866 hdd_err("country_code is null"); 867 return -EINVAL; 868 } 869 870 if (!ucfg_reg_is_user_country_set_allowed(hdd_ctx->psoc)) { 871 hdd_err("user_country is not allowed"); 872 return -EINVAL; 873 } 874 875 qdf_mem_copy(cc, country_code, REG_ALPHA2_LEN); 876 cc[REG_ALPHA2_LEN] = '\0'; 877 878 if (!qdf_mem_cmp(country_code, hdd_ctx->reg.alpha2, REG_ALPHA2_LEN)) { 879 cc_src = ucfg_reg_get_cc_and_src(hdd_ctx->psoc, alpha2); 880 if (cc_src == SOURCE_USERSPACE || cc_src == SOURCE_CORE) { 881 hdd_debug("country code is the same"); 882 return 0; 883 } 884 } 885 886 qdf_event_reset(&hdd_ctx->regulatory_update_event); 887 qdf_mutex_acquire(&hdd_ctx->regulatory_status_lock); 888 hdd_ctx->is_regulatory_update_in_progress = true; 889 qdf_mutex_release(&hdd_ctx->regulatory_status_lock); 890 891 status = ucfg_reg_set_country(hdd_ctx->pdev, cc); 892 if (QDF_IS_STATUS_ERROR(status)) { 893 hdd_err("Failed to set country"); 894 qdf_mutex_acquire(&hdd_ctx->regulatory_status_lock); 895 hdd_ctx->is_regulatory_update_in_progress = false; 896 qdf_mutex_release(&hdd_ctx->regulatory_status_lock); 897 } 898 899 hdd_reg_wait_for_country_change(hdd_ctx); 900 901 return qdf_status_to_os_return(status); 902 } 903 904 uint32_t hdd_reg_legacy_setband_to_reg_wifi_band_bitmap(uint8_t qca_setband) 905 { 906 uint32_t band_bitmap = 0; 907 908 switch (qca_setband) { 909 case QCA_SETBAND_AUTO: 910 band_bitmap |= REG_BAND_MASK_ALL; 911 break; 912 case QCA_SETBAND_5G: 913 band_bitmap |= BIT(REG_BAND_5G); 914 break; 915 case QCA_SETBAND_2G: 916 band_bitmap |= BIT(REG_BAND_2G); 917 break; 918 default: 919 hdd_err("Invalid band value %u", qca_setband); 920 return 0; 921 } 922 923 return band_bitmap; 924 } 925 926 int hdd_reg_set_band(struct net_device *dev, uint32_t band_bitmap) 927 { 928 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); 929 struct hdd_context *hdd_ctx; 930 uint32_t current_band; 931 QDF_STATUS status; 932 933 hdd_ctx = WLAN_HDD_GET_CTX(adapter); 934 935 if (!band_bitmap) { 936 hdd_err("Can't disable all bands"); 937 return -EINVAL; 938 } 939 940 hdd_debug("change band to %u", band_bitmap); 941 942 if (ucfg_reg_get_band(hdd_ctx->pdev, ¤t_band) != 943 QDF_STATUS_SUCCESS) { 944 hdd_debug("Failed to get current band config"); 945 return -EIO; 946 } 947 948 /* 949 * If SET_FCC_CHANNEL 0 command is received first then 6 GHz band would 950 * be disabled and band_capability would be set to 3 but existing 6 GHz 951 * STA and P2P client connections won't be disconnected. 952 * If set band comes again for 6 GHz band disabled and band_bitmap is 953 * equal to band_capability, proceed to disable 6 GHz band completely. 954 */ 955 if (current_band == band_bitmap && 956 !ucfg_reg_get_keep_6ghz_sta_cli_connection(hdd_ctx->pdev)) { 957 hdd_debug("band is the same so not updating"); 958 return 0; 959 } 960 961 hdd_ctx->curr_band = wlan_reg_band_bitmap_to_band_info(band_bitmap); 962 963 if (QDF_IS_STATUS_ERROR(ucfg_reg_set_band(hdd_ctx->pdev, 964 band_bitmap))) { 965 hdd_err("Failed to set the band bitmap value to %u", 966 band_bitmap); 967 return -EINVAL; 968 } 969 970 status = ucfg_cm_set_roam_band_update(hdd_ctx->psoc, 971 adapter->deflink->vdev_id); 972 if (QDF_IS_STATUS_ERROR(status)) 973 hdd_err("Failed to send RSO update to fw on set band"); 974 975 return 0; 976 } 977 978 /** 979 * hdd_restore_custom_reg_settings() - restore custom reg settings 980 * @wiphy: wiphy structure 981 * @country_alpha2: alpha2 of the country 982 * @reset: whether wiphy is reset 983 * 984 * Return: void 985 */ 986 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) 987 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0)) || defined(WITH_BACKPORTS) 988 static void hdd_restore_custom_reg_settings(struct wiphy *wiphy, 989 uint8_t *country_alpha2, 990 bool *reset) 991 { 992 } 993 #else 994 static void hdd_restore_custom_reg_settings(struct wiphy *wiphy, 995 uint8_t *country_alpha2, 996 bool *reset) 997 { 998 struct ieee80211_supported_band *sband; 999 enum nl80211_band band; 1000 struct ieee80211_channel *chan; 1001 int i; 1002 1003 if ((country_alpha2[0] == '0') && 1004 (country_alpha2[1] == '0') && 1005 (wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY)) { 1006 1007 for (band = 0; band < HDD_NUM_NL80211_BANDS; band++) { 1008 sband = wiphy->bands[band]; 1009 if (!sband) 1010 continue; 1011 for (i = 0; i < sband->n_channels; i++) { 1012 chan = &sband->channels[i]; 1013 chan->flags = chan->orig_flags; 1014 chan->max_antenna_gain = chan->orig_mag; 1015 chan->max_power = chan->orig_mpwr; 1016 } 1017 } 1018 *reset = true; 1019 } 1020 } 1021 #endif 1022 1023 /** 1024 * hdd_restore_reg_flags() - restore regulatory flags 1025 * @wiphy: device wiphy 1026 * @flags: regulatory flags 1027 * 1028 * Return: void 1029 */ 1030 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) 1031 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(WITH_BACKPORTS) 1032 static void hdd_restore_reg_flags(struct wiphy *wiphy, uint32_t flags) 1033 { 1034 wiphy->regulatory_flags = flags; 1035 } 1036 #else 1037 static void hdd_restore_reg_flags(struct wiphy *wiphy, uint32_t flags) 1038 { 1039 wiphy->flags = flags; 1040 } 1041 #endif 1042 1043 /** 1044 * hdd_reg_notifier() - regulatory notifier 1045 * @wiphy: wiphy 1046 * @request: regulatory request 1047 * 1048 * Return: void 1049 */ 1050 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) 1051 void hdd_reg_notifier(struct wiphy *wiphy, 1052 struct regulatory_request *request) 1053 { 1054 QDF_STATUS status = QDF_STATUS_SUCCESS; 1055 struct hdd_context *hdd_ctx = wiphy_priv(wiphy); 1056 char country[REG_ALPHA2_LEN + 1] = {0}; 1057 bool update_already_in_progress = 1058 hdd_ctx->is_regulatory_update_in_progress; 1059 1060 if (cds_is_driver_unloading() || cds_is_driver_recovering() || 1061 cds_is_driver_in_bad_state()) { 1062 hdd_err("unloading or ssr in progress, ignore"); 1063 return; 1064 } 1065 1066 if (hdd_ctx->is_wiphy_suspended) { 1067 hdd_err_rl("system/cfg80211 is already suspend"); 1068 return; 1069 } 1070 1071 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) { 1072 hdd_err_rl("Driver module is closed, dropping request"); 1073 return; 1074 } 1075 1076 hdd_debug("country: %c%c, initiator %d, dfs_region: %d", 1077 request->alpha2[0], 1078 request->alpha2[1], 1079 request->initiator, 1080 request->dfs_region); 1081 1082 switch (request->initiator) { 1083 case NL80211_REGDOM_SET_BY_USER: 1084 1085 if (request->user_reg_hint_type != 1086 NL80211_USER_REG_HINT_CELL_BASE) 1087 return; 1088 1089 qdf_event_reset(&hdd_ctx->regulatory_update_event); 1090 qdf_mutex_acquire(&hdd_ctx->regulatory_status_lock); 1091 hdd_ctx->is_regulatory_update_in_progress = true; 1092 qdf_mutex_release(&hdd_ctx->regulatory_status_lock); 1093 1094 qdf_mem_copy(country, request->alpha2, QDF_MIN( 1095 sizeof(request->alpha2), sizeof(country))); 1096 status = ucfg_reg_set_country(hdd_ctx->pdev, country); 1097 break; 1098 case NL80211_REGDOM_SET_BY_CORE: 1099 case NL80211_REGDOM_SET_BY_COUNTRY_IE: 1100 case NL80211_REGDOM_SET_BY_DRIVER: 1101 default: 1102 break; 1103 } 1104 1105 if (QDF_IS_STATUS_ERROR(status) && !update_already_in_progress) { 1106 hdd_err("Failed to set country"); 1107 qdf_mutex_acquire(&hdd_ctx->regulatory_status_lock); 1108 hdd_ctx->is_regulatory_update_in_progress = false; 1109 qdf_mutex_release(&hdd_ctx->regulatory_status_lock); 1110 } 1111 } 1112 #else 1113 void hdd_reg_notifier(struct wiphy *wiphy, 1114 struct regulatory_request *request) 1115 { 1116 struct hdd_context *hdd_ctx = wiphy_priv(wiphy); 1117 bool reset = false; 1118 enum dfs_reg dfs_reg; 1119 struct reg_config_vars config_vars; 1120 int ret_val; 1121 1122 hdd_debug("country: %c%c, initiator %d, dfs_region: %d", 1123 request->alpha2[0], 1124 request->alpha2[1], 1125 request->initiator, 1126 request->dfs_region); 1127 1128 if (!hdd_ctx) { 1129 hdd_err("invalid hdd_ctx pointer"); 1130 return; 1131 } 1132 1133 if (cds_is_driver_unloading() || cds_is_driver_recovering() || 1134 cds_is_driver_in_bad_state()) { 1135 hdd_err("unloading or ssr in progress, ignore"); 1136 return; 1137 } 1138 1139 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) { 1140 hdd_err("Driver module is closed; dropping request"); 1141 return; 1142 } 1143 1144 if (hdd_ctx->is_wiphy_suspended == true) { 1145 hdd_err("system/cfg80211 is already suspend"); 1146 return; 1147 } 1148 1149 if (('K' == request->alpha2[0]) && 1150 ('R' == request->alpha2[1])) 1151 request->dfs_region = (enum nl80211_dfs_regions)DFS_KR_REGION; 1152 1153 if (('C' == request->alpha2[0]) && 1154 ('N' == request->alpha2[1])) 1155 request->dfs_region = (enum nl80211_dfs_regions)DFS_CN_REGION; 1156 1157 /* first check if this callback is in response to the driver callback */ 1158 switch (request->initiator) { 1159 case NL80211_REGDOM_SET_BY_DRIVER: 1160 case NL80211_REGDOM_SET_BY_CORE: 1161 case NL80211_REGDOM_SET_BY_USER: 1162 1163 if ((false == init_by_driver) && 1164 (false == init_by_reg_core)) { 1165 1166 if (NL80211_REGDOM_SET_BY_CORE == request->initiator) 1167 return; 1168 init_by_reg_core = true; 1169 } 1170 1171 if ((NL80211_REGDOM_SET_BY_DRIVER == request->initiator) && 1172 (true == init_by_driver)) { 1173 1174 /* 1175 * restore the driver regulatory flags since 1176 * regulatory_hint may have 1177 * changed them 1178 */ 1179 hdd_restore_reg_flags(wiphy, hdd_ctx->reg.reg_flags); 1180 } 1181 1182 if (NL80211_REGDOM_SET_BY_CORE == request->initiator) { 1183 hdd_ctx->reg.cc_src = SOURCE_CORE; 1184 if (is_wiphy_custom_regulatory(wiphy)) 1185 reset = true; 1186 } else if (NL80211_REGDOM_SET_BY_DRIVER == request->initiator) { 1187 hdd_ctx->reg.cc_src = SOURCE_DRIVER; 1188 } else { 1189 hdd_ctx->reg.cc_src = SOURCE_USERSPACE; 1190 hdd_restore_custom_reg_settings(wiphy, 1191 request->alpha2, 1192 &reset); 1193 } 1194 1195 hdd_ctx->reg.alpha2[0] = request->alpha2[0]; 1196 hdd_ctx->reg.alpha2[1] = request->alpha2[1]; 1197 1198 ret_val = hdd_update_regulatory_info(hdd_ctx); 1199 if (ret_val) { 1200 hdd_err("invalid reg info, do not process"); 1201 return; 1202 } 1203 1204 hdd_process_regulatory_data(hdd_ctx, wiphy, reset); 1205 1206 sme_generic_change_country_code(hdd_ctx->mac_handle, 1207 hdd_ctx->reg.alpha2); 1208 1209 cds_fill_and_send_ctl_to_fw(&hdd_ctx->reg); 1210 1211 hdd_set_dfs_region(hdd_ctx, request->dfs_region); 1212 wlan_reg_get_dfs_region(hdd_ctx->pdev, &dfs_reg); 1213 1214 reg_program_config_vars(hdd_ctx, &config_vars); 1215 ucfg_reg_set_config_vars(hdd_ctx->psoc, config_vars); 1216 ucfg_reg_program_mas_chan_list(hdd_ctx->psoc, 1217 reg_channels, 1218 hdd_ctx->reg.alpha2, 1219 dfs_reg); 1220 break; 1221 1222 default: 1223 break; 1224 } 1225 } 1226 #endif 1227 1228 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) 1229 #if defined(WLAN_FEATURE_11BE) && defined(CFG80211_11BE_BASIC) 1230 static void fill_wiphy_channel_320mhz(struct ieee80211_channel *wiphy_chan, 1231 uint16_t max_bw) 1232 { 1233 if (max_bw < 320) 1234 wiphy_chan->flags |= IEEE80211_CHAN_NO_320MHZ; 1235 } 1236 #else 1237 static inline 1238 void fill_wiphy_channel_320mhz(struct ieee80211_channel *wiphy_chan, 1239 uint16_t max_bw) 1240 { 1241 } 1242 #endif 1243 1244 static void fill_wiphy_channel(struct ieee80211_channel *wiphy_chan, 1245 struct regulatory_channel *cur_chan) 1246 { 1247 1248 wiphy_chan->flags = 0; 1249 wiphy_chan->max_power = cur_chan->tx_power; 1250 1251 if (cur_chan->chan_flags & REGULATORY_CHAN_DISABLED) 1252 wiphy_chan->flags |= IEEE80211_CHAN_DISABLED; 1253 if (cur_chan->chan_flags & REGULATORY_CHAN_NO_IR) 1254 wiphy_chan->flags |= IEEE80211_CHAN_NO_IR; 1255 if (cur_chan->chan_flags & REGULATORY_CHAN_RADAR) 1256 wiphy_chan->flags |= IEEE80211_CHAN_RADAR; 1257 if (cur_chan->chan_flags & REGULATORY_CHAN_NO_OFDM) 1258 wiphy_chan->flags |= IEEE80211_CHAN_NO_OFDM; 1259 if (cur_chan->chan_flags & REGULATORY_CHAN_INDOOR_ONLY) 1260 wiphy_chan->flags |= IEEE80211_CHAN_INDOOR_ONLY; 1261 1262 if (cur_chan->max_bw < 10) 1263 wiphy_chan->flags |= IEEE80211_CHAN_NO_10MHZ; 1264 if (cur_chan->max_bw < 20) 1265 wiphy_chan->flags |= IEEE80211_CHAN_NO_20MHZ; 1266 if (cur_chan->max_bw < 40) 1267 wiphy_chan->flags |= IEEE80211_CHAN_NO_HT40; 1268 if (cur_chan->max_bw < 80) 1269 wiphy_chan->flags |= IEEE80211_CHAN_NO_80MHZ; 1270 if (cur_chan->max_bw < 160) 1271 wiphy_chan->flags |= IEEE80211_CHAN_NO_160MHZ; 1272 1273 fill_wiphy_channel_320mhz(wiphy_chan, cur_chan->max_bw); 1274 1275 wiphy_chan->orig_flags = wiphy_chan->flags; 1276 } 1277 1278 static void fill_wiphy_band_channels(struct wiphy *wiphy, 1279 struct regulatory_channel *cur_chan_list, 1280 uint8_t band_id) 1281 { 1282 uint32_t wiphy_num_chan, wiphy_index; 1283 uint32_t chan_cnt; 1284 struct ieee80211_channel *wiphy_chan; 1285 1286 if (!wiphy->bands[band_id]) 1287 return; 1288 1289 wiphy_num_chan = wiphy->bands[band_id]->n_channels; 1290 wiphy_chan = wiphy->bands[band_id]->channels; 1291 1292 for (wiphy_index = 0; wiphy_index < wiphy_num_chan; wiphy_index++) { 1293 for (chan_cnt = 0; chan_cnt < NUM_CHANNELS; chan_cnt++) { 1294 if (wiphy_chan[wiphy_index].center_freq == 1295 cur_chan_list[chan_cnt].center_freq) { 1296 fill_wiphy_channel(&(wiphy_chan[wiphy_index]), 1297 &(cur_chan_list[chan_cnt])); 1298 break; 1299 } 1300 } 1301 } 1302 } 1303 1304 #ifdef FEATURE_WLAN_CH_AVOID 1305 /** 1306 * hdd_ch_avoid_ind() - Avoid notified channels from FW handler 1307 * @hdd_ctxt: HDD context 1308 * @unsafe_chan_list: Channels that are unsafe 1309 * @avoid_freq_list: Frequencies to avoid 1310 * 1311 * Avoid channel notification from FW handler. 1312 * FW will send un-safe channel list to avoid over wrapping. 1313 * hostapd should not use notified channel 1314 * 1315 * Return: None 1316 */ 1317 void hdd_ch_avoid_ind(struct hdd_context *hdd_ctxt, 1318 struct unsafe_ch_list *unsafe_chan_list, 1319 struct ch_avoid_ind_type *avoid_freq_list) 1320 { 1321 uint16_t *local_unsafe_list; 1322 uint16_t local_unsafe_list_count; 1323 uint32_t restriction_mask; 1324 uint8_t i; 1325 1326 /* Basic sanity */ 1327 if (!hdd_ctxt) { 1328 hdd_err("Invalid arguments"); 1329 return; 1330 } 1331 1332 mutex_lock(&hdd_ctxt->avoid_freq_lock); 1333 qdf_mem_copy(&hdd_ctxt->coex_avoid_freq_list, avoid_freq_list, 1334 sizeof(struct ch_avoid_ind_type)); 1335 mutex_unlock(&hdd_ctxt->avoid_freq_lock); 1336 1337 restriction_mask = wlan_hdd_get_restriction_mask(hdd_ctxt); 1338 if (hdd_clone_local_unsafe_chan(hdd_ctxt, 1339 &local_unsafe_list, 1340 &local_unsafe_list_count) != 0) { 1341 hdd_err("failed to clone cur unsafe chan list"); 1342 return; 1343 } 1344 1345 /* clear existing unsafe channel cache */ 1346 hdd_ctxt->unsafe_channel_count = 0; 1347 qdf_mem_zero(hdd_ctxt->unsafe_channel_list, 1348 sizeof(hdd_ctxt->unsafe_channel_list)); 1349 1350 hdd_ctxt->unsafe_channel_count = unsafe_chan_list->chan_cnt; 1351 1352 wlan_hdd_set_restriction_mask(hdd_ctxt); 1353 1354 for (i = 0; i < unsafe_chan_list->chan_cnt; i++) { 1355 hdd_ctxt->unsafe_channel_list[i] = 1356 unsafe_chan_list->chan_freq_list[i]; 1357 } 1358 hdd_debug("number of unsafe channels is %d ", 1359 hdd_ctxt->unsafe_channel_count); 1360 1361 if (pld_set_wlan_unsafe_channel(hdd_ctxt->parent_dev, 1362 hdd_ctxt->unsafe_channel_list, 1363 hdd_ctxt->unsafe_channel_count)) { 1364 hdd_err("Failed to set unsafe channel"); 1365 1366 /* clear existing unsafe channel cache */ 1367 hdd_ctxt->unsafe_channel_count = 0; 1368 qdf_mem_zero(hdd_ctxt->unsafe_channel_list, 1369 sizeof(hdd_ctxt->unsafe_channel_list)); 1370 qdf_mem_free(local_unsafe_list); 1371 return; 1372 } 1373 1374 mutex_lock(&hdd_ctxt->avoid_freq_lock); 1375 if (hdd_ctxt->dnbs_avoid_freq_list.ch_avoid_range_cnt) 1376 if (wlan_hdd_merge_avoid_freqs(avoid_freq_list, 1377 &hdd_ctxt->dnbs_avoid_freq_list)) { 1378 mutex_unlock(&hdd_ctxt->avoid_freq_lock); 1379 hdd_debug("unable to merge avoid freqs"); 1380 qdf_mem_free(local_unsafe_list); 1381 return; 1382 } 1383 mutex_unlock(&hdd_ctxt->avoid_freq_lock); 1384 /* 1385 * first update the unsafe channel list to the platform driver and 1386 * send the avoid freq event to the application 1387 */ 1388 wlan_hdd_send_avoid_freq_event(hdd_ctxt, avoid_freq_list); 1389 1390 if (!hdd_ctxt->unsafe_channel_count) { 1391 hdd_debug("no unsafe channels - not restarting SAP"); 1392 qdf_mem_free(local_unsafe_list); 1393 return; 1394 } 1395 if (hdd_local_unsafe_channel_updated(hdd_ctxt, 1396 local_unsafe_list, 1397 local_unsafe_list_count, 1398 restriction_mask)) 1399 hdd_unsafe_channel_restart_sap(hdd_ctxt); 1400 qdf_mem_free(local_unsafe_list); 1401 1402 } 1403 #endif 1404 1405 #if defined CFG80211_USER_HINT_CELL_BASE_SELF_MANAGED || \ 1406 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0)) 1407 static void map_nl_reg_rule_flags(uint16_t drv_reg_rule_flag, 1408 uint32_t *regd_rule_flag) 1409 { 1410 if (drv_reg_rule_flag & REGULATORY_CHAN_NO_IR) 1411 *regd_rule_flag |= NL80211_RRF_NO_IR; 1412 if (drv_reg_rule_flag & REGULATORY_CHAN_RADAR) 1413 *regd_rule_flag |= NL80211_RRF_DFS; 1414 if (drv_reg_rule_flag & REGULATORY_CHAN_INDOOR_ONLY) 1415 *regd_rule_flag |= NL80211_RRF_NO_OUTDOOR; 1416 if (drv_reg_rule_flag & REGULATORY_CHAN_NO_OFDM) 1417 *regd_rule_flag |= NL80211_RRF_NO_OFDM; 1418 *regd_rule_flag |= NL80211_RRF_AUTO_BW; 1419 } 1420 1421 /** 1422 * dfs_reg_to_nl80211_dfs_regions() - convert dfs_reg to nl80211_dfs_regions 1423 * @dfs_region: DFS region 1424 * 1425 * Return: nl80211_dfs_regions 1426 */ 1427 static enum nl80211_dfs_regions dfs_reg_to_nl80211_dfs_regions( 1428 enum dfs_reg dfs_region) 1429 { 1430 switch (dfs_region) { 1431 case DFS_UNINIT_REGION: 1432 return NL80211_DFS_UNSET; 1433 case DFS_FCC_REGION: 1434 return NL80211_DFS_FCC; 1435 case DFS_ETSI_REGION: 1436 return NL80211_DFS_ETSI; 1437 case DFS_MKK_REGION: 1438 return NL80211_DFS_JP; 1439 default: 1440 return NL80211_DFS_UNSET; 1441 } 1442 } 1443 1444 /** 1445 * hdd_set_dfs_pri_multiplier() - Set dfs_pri_multiplier for ETSI region 1446 * @hdd_ctx: HDD context 1447 * @dfs_region: DFS region 1448 * 1449 * Return: none 1450 */ 1451 #ifdef DFS_PRI_MULTIPLIER 1452 static void hdd_set_dfs_pri_multiplier(struct hdd_context *hdd_ctx, 1453 enum dfs_reg dfs_region) 1454 { 1455 if (dfs_region == DFS_ETSI_REGION) 1456 wlan_sap_set_dfs_pri_multiplier(hdd_ctx->mac_handle); 1457 } 1458 #else 1459 static inline void hdd_set_dfs_pri_multiplier(struct hdd_context *hdd_ctx, 1460 enum dfs_reg dfs_region) 1461 { 1462 } 1463 #endif 1464 1465 void hdd_send_wiphy_regd_sync_event(struct hdd_context *hdd_ctx) 1466 { 1467 struct ieee80211_regdomain *regd; 1468 struct ieee80211_reg_rule *regd_rules; 1469 struct reg_rule_info reg_rules_struct; 1470 struct reg_rule_info *reg_rules; 1471 QDF_STATUS status; 1472 uint8_t i; 1473 1474 if (!hdd_ctx) { 1475 hdd_err("hdd_ctx is NULL"); 1476 return; 1477 } 1478 1479 status = ucfg_reg_get_regd_rules(hdd_ctx->pdev, ®_rules_struct); 1480 if (QDF_IS_STATUS_ERROR(status)) { 1481 hdd_err("could not get reg rules"); 1482 return; 1483 } 1484 1485 reg_rules = ®_rules_struct; 1486 if (!reg_rules->num_of_reg_rules) { 1487 hdd_err("no reg rules %d", reg_rules->num_of_reg_rules); 1488 return; 1489 } 1490 1491 regd = qdf_mem_malloc((reg_rules->num_of_reg_rules * 1492 sizeof(*regd_rules) + sizeof(*regd))); 1493 if (!regd) 1494 return; 1495 1496 regd->n_reg_rules = reg_rules->num_of_reg_rules; 1497 qdf_mem_copy(regd->alpha2, reg_rules->alpha2, REG_ALPHA2_LEN + 1); 1498 regd->dfs_region = 1499 dfs_reg_to_nl80211_dfs_regions(reg_rules->dfs_region); 1500 1501 hdd_set_dfs_pri_multiplier(hdd_ctx, reg_rules->dfs_region); 1502 1503 regd_rules = regd->reg_rules; 1504 hdd_debug("Regulatory Domain %s", regd->alpha2); 1505 hdd_debug("start freq\tend freq\t@ max_bw\tant_gain\tpwr\tflags"); 1506 for (i = 0; i < reg_rules->num_of_reg_rules; i++) { 1507 regd_rules[i].freq_range.start_freq_khz = 1508 reg_rules->reg_rules[i].start_freq * 1000; 1509 regd_rules[i].freq_range.end_freq_khz = 1510 reg_rules->reg_rules[i].end_freq * 1000; 1511 regd_rules[i].freq_range.max_bandwidth_khz = 1512 reg_rules->reg_rules[i].max_bw * 1000; 1513 regd_rules[i].power_rule.max_antenna_gain = 1514 reg_rules->reg_rules[i].ant_gain * 100; 1515 regd_rules[i].power_rule.max_eirp = 1516 reg_rules->reg_rules[i].reg_power * 100; 1517 map_nl_reg_rule_flags(reg_rules->reg_rules[i].flags, 1518 ®d_rules[i].flags); 1519 hdd_debug("%d KHz\t%d KHz\t@ %d KHz\t%d\t\t%d\t%d", 1520 regd_rules[i].freq_range.start_freq_khz, 1521 regd_rules[i].freq_range.end_freq_khz, 1522 regd_rules[i].freq_range.max_bandwidth_khz, 1523 regd_rules[i].power_rule.max_antenna_gain, 1524 regd_rules[i].power_rule.max_eirp, 1525 regd_rules[i].flags); 1526 } 1527 1528 regulatory_set_wiphy_regd(hdd_ctx->wiphy, regd); 1529 1530 hdd_debug("regd sync event sent with reg rules info"); 1531 qdf_mem_free(regd); 1532 } 1533 #endif 1534 1535 #if defined(CONFIG_BAND_6GHZ) && (defined(CFG80211_6GHZ_BAND_SUPPORTED) || \ 1536 (KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE)) 1537 static void 1538 fill_wiphy_6ghz_band_channels(struct wiphy *wiphy, 1539 struct regulatory_channel *chan_list) 1540 { 1541 fill_wiphy_band_channels(wiphy, chan_list, NL80211_BAND_6GHZ); 1542 } 1543 #else 1544 static void 1545 fill_wiphy_6ghz_band_channels(struct wiphy *wiphy, 1546 struct regulatory_channel *chan_list) 1547 { 1548 } 1549 #endif 1550 1551 #define HDD_MAX_CHAN_INFO_LOG 192 1552 1553 /** 1554 * hdd_regulatory_chanlist_dump() - Dump regulatory channel list info 1555 * @chan_list: regulatory channel list 1556 * 1557 * Return: void 1558 */ 1559 static void hdd_regulatory_chanlist_dump(struct regulatory_channel *chan_list) 1560 { 1561 uint32_t i; 1562 uint8_t info[HDD_MAX_CHAN_INFO_LOG]; 1563 int len = 0; 1564 struct regulatory_channel *chan; 1565 uint32_t count = 0; 1566 int ret; 1567 1568 hdd_debug("start (freq MHz, tx power dBm):"); 1569 for (i = 0; i < NUM_CHANNELS; i++) { 1570 chan = &chan_list[i]; 1571 if ((chan->chan_flags & REGULATORY_CHAN_DISABLED)) 1572 continue; 1573 count++; 1574 ret = scnprintf(info + len, sizeof(info) - len, "%d %d ", 1575 chan->center_freq, chan->tx_power); 1576 if (ret <= 0) 1577 break; 1578 len += ret; 1579 if (len >= (sizeof(info) - 20)) { 1580 hdd_debug("%s", info); 1581 len = 0; 1582 } 1583 } 1584 if (len > 0) 1585 hdd_debug("%s", info); 1586 hdd_debug("end total_count %d", count); 1587 } 1588 1589 #ifdef FEATURE_WLAN_CH_AVOID_EXT 1590 /** 1591 * hdd_country_change_bw_check() - Check if bandwidth changed 1592 * @link_info: Link info pointer in HDD adapter 1593 * @oper_freq: current frequency of adapter 1594 * 1595 * Return: true if bandwidth changed otherwise false. 1596 */ 1597 static bool hdd_country_change_bw_check(struct wlan_hdd_link_info *link_info, 1598 qdf_freq_t oper_freq) 1599 { 1600 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter); 1601 bool width_changed = false; 1602 enum phy_ch_width width; 1603 uint16_t org_bw = 0; 1604 struct regulatory_channel *cur_chan_list = NULL; 1605 int i; 1606 1607 cur_chan_list = qdf_mem_malloc(sizeof(*cur_chan_list) * NUM_CHANNELS); 1608 if (!cur_chan_list) 1609 return false; 1610 1611 ucfg_reg_get_current_chan_list(hdd_ctx->pdev, cur_chan_list); 1612 1613 width = hdd_get_link_info_width(link_info); 1614 org_bw = wlan_reg_get_bw_value(width); 1615 1616 for (i = 0; i < NUM_CHANNELS; i++) { 1617 if (cur_chan_list[i].state == 1618 CHANNEL_STATE_DISABLE) 1619 continue; 1620 1621 if (cur_chan_list[i].center_freq == oper_freq && 1622 org_bw > cur_chan_list[i].max_bw) { 1623 width_changed = true; 1624 break; 1625 } 1626 } 1627 qdf_mem_free(cur_chan_list); 1628 return width_changed; 1629 } 1630 #else 1631 static inline bool 1632 hdd_country_change_bw_check(struct wlan_hdd_link_info *link_info, 1633 qdf_freq_t oper_freq) 1634 { 1635 return false; 1636 } 1637 #endif 1638 1639 /** 1640 * hdd_country_change_update_sta() - handle country code change for STA 1641 * @hdd_ctx: Global HDD context 1642 * 1643 * This function handles the stop/start/restart of STA/P2P_CLI adapters when 1644 * the country code changes 1645 * 1646 * Return: none 1647 */ 1648 static void hdd_country_change_update_sta(struct hdd_context *hdd_ctx) 1649 { 1650 struct hdd_adapter *adapter = NULL, *next_adapter = NULL; 1651 struct hdd_station_ctx *sta_ctx = NULL; 1652 struct wlan_objmgr_pdev *pdev = NULL; 1653 uint32_t new_phy_mode; 1654 bool freq_changed, phy_changed, width_changed; 1655 qdf_freq_t oper_freq; 1656 eCsrPhyMode csr_phy_mode; 1657 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_COUNTRY_CHANGE_UPDATE_STA; 1658 struct wlan_hdd_link_info *link_info; 1659 enum qca_wlan_vendor_phy_mode vendor_phy_mode = 1660 QCA_WLAN_VENDOR_PHY_MODE_AUTO; 1661 1662 pdev = hdd_ctx->pdev; 1663 1664 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter, 1665 dbgid) { 1666 hdd_adapter_for_each_active_link_info(adapter, link_info) { 1667 width_changed = false; 1668 oper_freq = hdd_get_link_info_home_channel(link_info); 1669 if (oper_freq) 1670 freq_changed = wlan_reg_is_disable_for_pwrmode( 1671 pdev, oper_freq, 1672 REG_CURRENT_PWR_MODE); 1673 else 1674 freq_changed = false; 1675 1676 switch (adapter->device_mode) { 1677 case QDF_P2P_CLIENT_MODE: 1678 /* 1679 * P2P client is the same as STA 1680 * continue to next statement 1681 */ 1682 case QDF_STA_MODE: 1683 sta_ctx = 1684 WLAN_HDD_GET_STATION_CTX_PTR(link_info); 1685 new_phy_mode = wlan_reg_get_max_phymode(pdev, 1686 REG_PHYMODE_MAX, 1687 oper_freq); 1688 csr_phy_mode = 1689 csr_convert_from_reg_phy_mode(new_phy_mode); 1690 phy_changed = 1691 (sta_ctx->reg_phymode != csr_phy_mode); 1692 1693 width_changed = 1694 hdd_country_change_bw_check(link_info, 1695 oper_freq); 1696 1697 if (!hdd_is_vdev_in_conn_state(link_info)) { 1698 hdd_set_vdev_phy_mode(adapter, 1699 vendor_phy_mode); 1700 continue; 1701 } 1702 1703 if (phy_changed || freq_changed || 1704 width_changed) { 1705 hdd_debug("changed: phy %d, freq %d, width %d", 1706 phy_changed, freq_changed, 1707 width_changed); 1708 wlan_hdd_cm_issue_disconnect( 1709 link_info, 1710 REASON_UNSPEC_FAILURE, 1711 false); 1712 hdd_set_vdev_phy_mode(adapter, 1713 vendor_phy_mode); 1714 sta_ctx->reg_phymode = csr_phy_mode; 1715 } else { 1716 hdd_debug("Remain on current channel but update tx power"); 1717 wlan_reg_update_tx_power_on_ctry_change( 1718 pdev, 1719 link_info->vdev_id); 1720 } 1721 sme_set_vdev_ies_per_band(hdd_ctx->mac_handle, 1722 link_info->vdev_id, 1723 QDF_STA_MODE); 1724 break; 1725 default: 1726 break; 1727 } 1728 } 1729 /* dev_put has to be done here */ 1730 hdd_adapter_dev_put_debug(adapter, dbgid); 1731 } 1732 } 1733 1734 /** 1735 * hdd_restart_sap_with_new_phymode() - restart the SAP with the new phymode 1736 * @link_info: Link info pointer in HDD adapter. 1737 * @sap_config: sap configuration pointer 1738 * @csr_phy_mode: phymode to restart SAP with 1739 * 1740 * This function handles the stop/start/restart of SAP/P2P_GO adapters when the 1741 * country code changes 1742 * 1743 * Return: none 1744 */ 1745 static void 1746 hdd_restart_sap_with_new_phymode(struct wlan_hdd_link_info *link_info, 1747 struct sap_config *sap_config, 1748 eCsrPhyMode csr_phy_mode) 1749 { 1750 struct hdd_adapter *adapter = link_info->adapter; 1751 struct hdd_context *hdd_ctx = adapter->hdd_ctx; 1752 struct hdd_hostapd_state *hostapd_state = NULL; 1753 struct sap_context *sap_ctx = NULL; 1754 QDF_STATUS status; 1755 1756 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(link_info); 1757 sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(link_info); 1758 1759 if (!test_bit(SOFTAP_BSS_STARTED, &link_info->link_flags)) { 1760 sap_config->sap_orig_hw_mode = sap_config->SapHw_mode; 1761 sap_config->SapHw_mode = csr_phy_mode; 1762 hdd_err("Can't restart AP because it is not started"); 1763 return; 1764 } 1765 1766 qdf_event_reset(&hostapd_state->qdf_stop_bss_event); 1767 status = wlansap_stop_bss(sap_ctx); 1768 if (!QDF_IS_STATUS_SUCCESS(status)) { 1769 hdd_err("SAP Stop Bss fail"); 1770 return; 1771 } 1772 status = qdf_wait_single_event(&hostapd_state->qdf_stop_bss_event, 1773 SME_CMD_STOP_BSS_TIMEOUT); 1774 if (!QDF_IS_STATUS_SUCCESS(status)) { 1775 hdd_err("SAP Stop timeout"); 1776 return; 1777 } 1778 1779 sap_config->chan_freq = 1780 wlansap_get_safe_channel_from_pcl_and_acs_range(sap_ctx, NULL); 1781 1782 sap_config->sap_orig_hw_mode = sap_config->SapHw_mode; 1783 sap_config->SapHw_mode = csr_phy_mode; 1784 1785 mutex_lock(&hdd_ctx->sap_lock); 1786 qdf_event_reset(&hostapd_state->qdf_event); 1787 status = wlansap_start_bss(sap_ctx, hdd_hostapd_sap_event_cb, 1788 sap_config, adapter->dev); 1789 if (!QDF_IS_STATUS_SUCCESS(status)) { 1790 mutex_unlock(&hdd_ctx->sap_lock); 1791 hdd_err("SAP Start Bss fail"); 1792 return; 1793 } 1794 status = qdf_wait_single_event(&hostapd_state->qdf_event, 1795 SME_CMD_START_BSS_TIMEOUT); 1796 if (!QDF_IS_STATUS_SUCCESS(status)) { 1797 mutex_unlock(&hdd_ctx->sap_lock); 1798 hdd_err("SAP Start timeout"); 1799 return; 1800 } 1801 mutex_unlock(&hdd_ctx->sap_lock); 1802 } 1803 1804 /** 1805 * hdd_country_change_update_sap() - handle country code change for SAP 1806 * @hdd_ctx: Global HDD context 1807 * 1808 * This function handles the stop/start/restart of SAP/P2P_GO adapters when the 1809 * country code changes 1810 * 1811 * Return: none 1812 */ 1813 static void hdd_country_change_update_sap(struct hdd_context *hdd_ctx) 1814 { 1815 struct hdd_adapter *adapter = NULL, *next_adapter = NULL; 1816 struct sap_config *sap_config = NULL; 1817 struct wlan_objmgr_pdev *pdev = NULL; 1818 uint32_t reg_phy_mode, new_phy_mode; 1819 bool phy_changed; 1820 qdf_freq_t oper_freq; 1821 eCsrPhyMode csr_phy_mode; 1822 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_COUNTRY_CHANGE_UPDATE_SAP; 1823 struct wlan_hdd_link_info *link_info; 1824 1825 pdev = hdd_ctx->pdev; 1826 1827 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter, 1828 dbgid) { 1829 hdd_adapter_for_each_active_link_info(adapter, link_info) { 1830 oper_freq = hdd_get_link_info_home_channel(link_info); 1831 1832 switch (adapter->device_mode) { 1833 case QDF_P2P_GO_MODE: 1834 policy_mgr_check_sap_restart(hdd_ctx->psoc, 1835 link_info->vdev_id); 1836 break; 1837 case QDF_SAP_MODE: 1838 if (!test_bit(SOFTAP_INIT_DONE, 1839 &link_info->link_flags)) { 1840 hdd_info("AP is not started yet"); 1841 break; 1842 } 1843 sap_config = &link_info->session.ap.sap_config; 1844 reg_phy_mode = csr_convert_to_reg_phy_mode( 1845 sap_config->sap_orig_hw_mode, 1846 oper_freq); 1847 new_phy_mode = wlan_reg_get_max_phymode(pdev, 1848 reg_phy_mode, 1849 oper_freq); 1850 csr_phy_mode = 1851 csr_convert_from_reg_phy_mode(new_phy_mode); 1852 phy_changed = 1853 (csr_phy_mode != sap_config->SapHw_mode); 1854 1855 if (phy_changed) 1856 hdd_restart_sap_with_new_phymode(link_info, 1857 sap_config, 1858 csr_phy_mode); 1859 else 1860 policy_mgr_check_sap_restart( 1861 hdd_ctx->psoc, 1862 link_info->vdev_id); 1863 hdd_debug("Update tx power due to ctry change"); 1864 wlan_reg_update_tx_power_on_ctry_change( 1865 pdev, link_info->vdev_id); 1866 break; 1867 default: 1868 break; 1869 } 1870 } 1871 /* dev_put has to be done here */ 1872 hdd_adapter_dev_put_debug(adapter, dbgid); 1873 } 1874 } 1875 1876 static void __hdd_country_change_work_handle(struct hdd_context *hdd_ctx) 1877 { 1878 /* 1879 * Loop over STAs first since it may lead to different channel 1880 * selection for SAPs 1881 */ 1882 hdd_country_change_update_sta(hdd_ctx); 1883 sme_generic_change_country_code(hdd_ctx->mac_handle, 1884 hdd_ctx->reg.alpha2); 1885 1886 qdf_event_set_all(&hdd_ctx->regulatory_update_event); 1887 qdf_mutex_acquire(&hdd_ctx->regulatory_status_lock); 1888 hdd_ctx->is_regulatory_update_in_progress = false; 1889 qdf_mutex_release(&hdd_ctx->regulatory_status_lock); 1890 1891 hdd_country_change_update_sap(hdd_ctx); 1892 } 1893 1894 /** 1895 * hdd_handle_country_change_work_error() - handle country code change error 1896 * @hdd_ctx: Global HDD context 1897 * @errno: country code change error number 1898 * 1899 * This function handles error code in country code change worker 1900 * 1901 * Return: none 1902 */ 1903 static void hdd_handle_country_change_work_error(struct hdd_context *hdd_ctx, 1904 int errno) 1905 { 1906 if (errno == -EAGAIN) { 1907 qdf_sleep(COUNTRY_CHANGE_WORK_RESCHED_WAIT_TIME); 1908 hdd_debug("rescheduling country change work"); 1909 qdf_sched_work(0, &hdd_ctx->country_change_work); 1910 } else { 1911 hdd_err("can not handle country change %d", errno); 1912 qdf_event_set_all(&hdd_ctx->regulatory_update_event); 1913 qdf_mutex_acquire(&hdd_ctx->regulatory_status_lock); 1914 hdd_ctx->is_regulatory_update_in_progress = false; 1915 qdf_mutex_release(&hdd_ctx->regulatory_status_lock); 1916 } 1917 } 1918 1919 /** 1920 * hdd_country_change_work_handle() - handle country code change 1921 * @arg: Global HDD context 1922 * 1923 * This function handles the stop/start/restart of all adapters when the 1924 * country code changes 1925 * 1926 * Return: none 1927 */ 1928 static void hdd_country_change_work_handle(void *arg) 1929 { 1930 struct hdd_context *hdd_ctx = (struct hdd_context *)arg; 1931 struct osif_psoc_sync *psoc_sync; 1932 int errno; 1933 1934 errno = wlan_hdd_validate_context(hdd_ctx); 1935 if (errno) 1936 return hdd_handle_country_change_work_error(hdd_ctx, errno); 1937 1938 errno = osif_psoc_sync_op_start(wiphy_dev(hdd_ctx->wiphy), &psoc_sync); 1939 if (errno) 1940 return hdd_handle_country_change_work_error(hdd_ctx, errno); 1941 1942 if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) 1943 hdd_err("Driver disabled, ignore country code change"); 1944 else 1945 __hdd_country_change_work_handle(hdd_ctx); 1946 1947 osif_psoc_sync_op_stop(psoc_sync); 1948 } 1949 1950 static void hdd_regulatory_dyn_cbk(struct wlan_objmgr_psoc *psoc, 1951 struct wlan_objmgr_pdev *pdev, 1952 struct regulatory_channel *chan_list, 1953 struct avoid_freq_ind_data *avoid_freq_ind, 1954 void *arg) 1955 { 1956 struct wiphy *wiphy; 1957 struct pdev_osif_priv *pdev_priv; 1958 struct hdd_context *hdd_ctx; 1959 enum country_src cc_src; 1960 uint8_t alpha2[REG_ALPHA2_LEN + 1]; 1961 bool nb_flag; 1962 bool reg_flag; 1963 1964 pdev_priv = wlan_pdev_get_ospriv(pdev); 1965 wiphy = pdev_priv->wiphy; 1966 hdd_ctx = wiphy_priv(wiphy); 1967 1968 nb_flag = ucfg_mlme_get_coex_unsafe_chan_nb_user_prefer_for_sap( 1969 hdd_ctx->psoc); 1970 reg_flag = ucfg_mlme_get_coex_unsafe_chan_reg_disable(hdd_ctx->psoc); 1971 1972 if (avoid_freq_ind && nb_flag && reg_flag) 1973 goto sync_chanlist; 1974 1975 if (avoid_freq_ind) { 1976 hdd_ch_avoid_ind(hdd_ctx, &avoid_freq_ind->chan_list, 1977 &avoid_freq_ind->freq_list); 1978 return; 1979 } 1980 1981 sync_chanlist: 1982 1983 hdd_debug("process channel list update from regulatory"); 1984 hdd_regulatory_chanlist_dump(chan_list); 1985 1986 fill_wiphy_band_channels(wiphy, chan_list, NL80211_BAND_2GHZ); 1987 fill_wiphy_band_channels(wiphy, chan_list, NL80211_BAND_5GHZ); 1988 fill_wiphy_6ghz_band_channels(wiphy, chan_list); 1989 cc_src = ucfg_reg_get_cc_and_src(hdd_ctx->psoc, alpha2); 1990 qdf_mem_copy(hdd_ctx->reg.alpha2, alpha2, REG_ALPHA2_LEN + 1); 1991 1992 /* Check the kernel version for upstream commit aced43ce780dc5 that 1993 * has support for processing user cell_base hints when wiphy is 1994 * self managed or check the backport flag for the same. 1995 */ 1996 #if defined CFG80211_USER_HINT_CELL_BASE_SELF_MANAGED || \ 1997 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0)) 1998 if (wiphy->registered) 1999 hdd_send_wiphy_regd_sync_event(hdd_ctx); 2000 #endif 2001 2002 hdd_config_tdls_with_band_switch(hdd_ctx); 2003 qdf_sched_work(0, &hdd_ctx->country_change_work); 2004 } 2005 2006 int hdd_update_regulatory_config(struct hdd_context *hdd_ctx) 2007 { 2008 struct reg_config_vars config_vars; 2009 2010 reg_program_config_vars(hdd_ctx, &config_vars); 2011 ucfg_reg_set_config_vars(hdd_ctx->psoc, config_vars); 2012 return 0; 2013 } 2014 2015 int hdd_init_regulatory_update_event(struct hdd_context *hdd_ctx) 2016 { 2017 QDF_STATUS status; 2018 2019 status = qdf_event_create(&hdd_ctx->regulatory_update_event); 2020 if (QDF_IS_STATUS_ERROR(status)) { 2021 hdd_err("Failed to create regulatory update event"); 2022 goto failure; 2023 } 2024 status = qdf_mutex_create(&hdd_ctx->regulatory_status_lock); 2025 if (QDF_IS_STATUS_ERROR(status)) { 2026 hdd_err("Failed to create regulatory status mutex"); 2027 goto failure; 2028 } 2029 hdd_ctx->is_regulatory_update_in_progress = false; 2030 2031 failure: 2032 return qdf_status_to_os_return(status); 2033 } 2034 2035 int hdd_regulatory_init(struct hdd_context *hdd_ctx, struct wiphy *wiphy) 2036 { 2037 bool offload_enabled; 2038 struct regulatory_channel *cur_chan_list; 2039 int ret; 2040 2041 cur_chan_list = qdf_mem_malloc(sizeof(*cur_chan_list) * NUM_CHANNELS); 2042 if (!cur_chan_list) { 2043 return -ENOMEM; 2044 } 2045 2046 qdf_create_work(0, &hdd_ctx->country_change_work, 2047 hdd_country_change_work_handle, hdd_ctx); 2048 ucfg_reg_register_chan_change_callback(hdd_ctx->psoc, 2049 hdd_regulatory_dyn_cbk, 2050 NULL); 2051 2052 ret = hdd_update_country_code(hdd_ctx); 2053 if (ret) { 2054 hdd_err("Failed to update country code; errno:%d", ret); 2055 return -EINVAL; 2056 } 2057 2058 wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED; 2059 /* Check the kernel version for upstream commit aced43ce780dc5 that 2060 * has support for processing user cell_base hints when wiphy is 2061 * self managed or check the backport flag for the same. 2062 */ 2063 #if defined CFG80211_USER_HINT_CELL_BASE_SELF_MANAGED || \ 2064 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0)) 2065 wiphy->features |= NL80211_FEATURE_CELL_BASE_REG_HINTS; 2066 #endif 2067 wiphy->reg_notifier = hdd_reg_notifier; 2068 offload_enabled = ucfg_reg_is_regdb_offloaded(hdd_ctx->psoc); 2069 hdd_debug("regulatory offload_enabled %d", offload_enabled); 2070 if (offload_enabled) 2071 hdd_ctx->reg_offload = true; 2072 else 2073 hdd_ctx->reg_offload = false; 2074 2075 ucfg_reg_get_current_chan_list(hdd_ctx->pdev, cur_chan_list); 2076 hdd_regulatory_chanlist_dump(cur_chan_list); 2077 fill_wiphy_band_channels(wiphy, cur_chan_list, NL80211_BAND_2GHZ); 2078 fill_wiphy_band_channels(wiphy, cur_chan_list, NL80211_BAND_5GHZ); 2079 fill_wiphy_6ghz_band_channels(wiphy, cur_chan_list); 2080 qdf_mem_zero(hdd_ctx->reg.alpha2, REG_ALPHA2_LEN + 1); 2081 2082 qdf_mem_free(cur_chan_list); 2083 return 0; 2084 } 2085 2086 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) 2087 int hdd_regulatory_init(struct hdd_context *hdd_ctx, struct wiphy *wiphy) 2088 { 2089 hdd_ctx->reg_offload = false; 2090 wiphy->reg_notifier = hdd_reg_notifier; 2091 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS; 2092 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE; 2093 hdd_regulatory_init_no_offload(hdd_ctx, wiphy); 2094 2095 return 0; 2096 } 2097 2098 #else 2099 int hdd_regulatory_init(struct hdd_context *hdd_ctx, struct wiphy *wiphy) 2100 { 2101 hdd_ctx->reg_offload = false; 2102 wiphy->reg_notifier = hdd_reg_notifier; 2103 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS; 2104 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE; 2105 hdd_regulatory_init_no_offload(hdd_ctx, wiphy); 2106 2107 return 0; 2108 } 2109 #endif 2110 2111 void hdd_deinit_regulatory_update_event(struct hdd_context *hdd_ctx) 2112 { 2113 QDF_STATUS status; 2114 2115 status = qdf_event_destroy(&hdd_ctx->regulatory_update_event); 2116 if (QDF_IS_STATUS_ERROR(status)) 2117 hdd_err("Failed to destroy regulatory update event"); 2118 status = qdf_mutex_destroy(&hdd_ctx->regulatory_status_lock); 2119 if (QDF_IS_STATUS_ERROR(status)) 2120 hdd_err("Failed to destroy regulatory status mutex"); 2121 } 2122 2123 void hdd_regulatory_deinit(struct hdd_context *hdd_ctx) 2124 { 2125 qdf_flush_work(&hdd_ctx->country_change_work); 2126 qdf_destroy_work(0, &hdd_ctx->country_change_work); 2127 } 2128 2129 void hdd_update_regdb_offload_config(struct hdd_context *hdd_ctx) 2130 { 2131 bool ignore_fw_reg_offload_ind = false; 2132 2133 ucfg_mlme_get_ignore_fw_reg_offload_ind(hdd_ctx->psoc, 2134 &ignore_fw_reg_offload_ind); 2135 if (!ignore_fw_reg_offload_ind) { 2136 hdd_debug("regdb offload is based on firmware capability"); 2137 return; 2138 } 2139 2140 hdd_debug("Ignore regdb offload Indication from FW"); 2141 ucfg_set_ignore_fw_reg_offload_ind(hdd_ctx->psoc); 2142 } 2143