regd.c revision bc0aa0691806dc30cf1a69fe50ae90cf8f752977
1/* 2 * Copyright (c) 2008-2009 Atheros Communications Inc. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 18 19#include <linux/kernel.h> 20#include <linux/export.h> 21#include <net/cfg80211.h> 22#include <net/mac80211.h> 23#include "regd.h" 24#include "regd_common.h" 25 26static int __ath_regd_init(struct ath_regulatory *reg); 27 28/* 29 * This is a set of common rules used by our world regulatory domains. 30 * We have 12 world regulatory domains. To save space we consolidate 31 * the regulatory domains in 5 structures by frequency and change 32 * the flags on our reg_notifier() on a case by case basis. 33 */ 34 35/* Only these channels all allow active scan on all world regulatory domains */ 36#define ATH9K_2GHZ_CH01_11 REG_RULE(2412-10, 2462+10, 40, 0, 20, 0) 37 38/* We enable active scan on these a case by case basis by regulatory domain */ 39#define ATH9K_2GHZ_CH12_13 REG_RULE(2467-10, 2472+10, 40, 0, 20,\ 40 NL80211_RRF_NO_IR) 41#define ATH9K_2GHZ_CH14 REG_RULE(2484-10, 2484+10, 40, 0, 20,\ 42 NL80211_RRF_NO_IR | \ 43 NL80211_RRF_NO_OFDM) 44 45/* We allow IBSS on these on a case by case basis by regulatory domain */ 46#define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5350+10, 80, 0, 30,\ 47 NL80211_RRF_NO_IR) 48#define ATH9K_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 80, 0, 30,\ 49 NL80211_RRF_NO_IR) 50#define ATH9K_5GHZ_5725_5850 REG_RULE(5725-10, 5850+10, 80, 0, 30,\ 51 NL80211_RRF_NO_IR) 52 53#define ATH9K_2GHZ_ALL ATH9K_2GHZ_CH01_11, \ 54 ATH9K_2GHZ_CH12_13, \ 55 ATH9K_2GHZ_CH14 56 57#define ATH9K_5GHZ_ALL ATH9K_5GHZ_5150_5350, \ 58 ATH9K_5GHZ_5470_5850 59 60/* This one skips what we call "mid band" */ 61#define ATH9K_5GHZ_NO_MIDBAND ATH9K_5GHZ_5150_5350, \ 62 ATH9K_5GHZ_5725_5850 63 64/* Can be used for: 65 * 0x60, 0x61, 0x62 */ 66static const struct ieee80211_regdomain ath_world_regdom_60_61_62 = { 67 .n_reg_rules = 5, 68 .alpha2 = "99", 69 .reg_rules = { 70 ATH9K_2GHZ_ALL, 71 ATH9K_5GHZ_ALL, 72 } 73}; 74 75/* Can be used by 0x63 and 0x65 */ 76static const struct ieee80211_regdomain ath_world_regdom_63_65 = { 77 .n_reg_rules = 4, 78 .alpha2 = "99", 79 .reg_rules = { 80 ATH9K_2GHZ_CH01_11, 81 ATH9K_2GHZ_CH12_13, 82 ATH9K_5GHZ_NO_MIDBAND, 83 } 84}; 85 86/* Can be used by 0x64 only */ 87static const struct ieee80211_regdomain ath_world_regdom_64 = { 88 .n_reg_rules = 3, 89 .alpha2 = "99", 90 .reg_rules = { 91 ATH9K_2GHZ_CH01_11, 92 ATH9K_5GHZ_NO_MIDBAND, 93 } 94}; 95 96/* Can be used by 0x66 and 0x69 */ 97static const struct ieee80211_regdomain ath_world_regdom_66_69 = { 98 .n_reg_rules = 3, 99 .alpha2 = "99", 100 .reg_rules = { 101 ATH9K_2GHZ_CH01_11, 102 ATH9K_5GHZ_ALL, 103 } 104}; 105 106/* Can be used by 0x67, 0x68, 0x6A and 0x6C */ 107static const struct ieee80211_regdomain ath_world_regdom_67_68_6A_6C = { 108 .n_reg_rules = 4, 109 .alpha2 = "99", 110 .reg_rules = { 111 ATH9K_2GHZ_CH01_11, 112 ATH9K_2GHZ_CH12_13, 113 ATH9K_5GHZ_ALL, 114 } 115}; 116 117static inline bool is_wwr_sku(u16 regd) 118{ 119 return ((regd & COUNTRY_ERD_FLAG) != COUNTRY_ERD_FLAG) && 120 (((regd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX) || 121 (regd == WORLD)); 122} 123 124static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg) 125{ 126 return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG; 127} 128 129bool ath_is_world_regd(struct ath_regulatory *reg) 130{ 131 return is_wwr_sku(ath_regd_get_eepromRD(reg)); 132} 133EXPORT_SYMBOL(ath_is_world_regd); 134 135static const struct ieee80211_regdomain *ath_default_world_regdomain(void) 136{ 137 /* this is the most restrictive */ 138 return &ath_world_regdom_64; 139} 140 141static const struct 142ieee80211_regdomain *ath_world_regdomain(struct ath_regulatory *reg) 143{ 144 switch (reg->regpair->regDmnEnum) { 145 case 0x60: 146 case 0x61: 147 case 0x62: 148 return &ath_world_regdom_60_61_62; 149 case 0x63: 150 case 0x65: 151 return &ath_world_regdom_63_65; 152 case 0x64: 153 return &ath_world_regdom_64; 154 case 0x66: 155 case 0x69: 156 return &ath_world_regdom_66_69; 157 case 0x67: 158 case 0x68: 159 case 0x6A: 160 case 0x6C: 161 return &ath_world_regdom_67_68_6A_6C; 162 default: 163 WARN_ON(1); 164 return ath_default_world_regdomain(); 165 } 166} 167 168bool ath_is_49ghz_allowed(u16 regdomain) 169{ 170 /* possibly more */ 171 return regdomain == MKK9_MKKC; 172} 173EXPORT_SYMBOL(ath_is_49ghz_allowed); 174 175/* Frequency is one where radar detection is required */ 176static bool ath_is_radar_freq(u16 center_freq) 177{ 178 return (center_freq >= 5260 && center_freq <= 5700); 179} 180 181static void ath_force_clear_no_ir_chan(struct wiphy *wiphy, 182 struct ieee80211_channel *ch) 183{ 184 const struct ieee80211_reg_rule *reg_rule; 185 186 reg_rule = freq_reg_info(wiphy, ch->center_freq); 187 if (IS_ERR(reg_rule)) 188 return; 189 190 if (!(reg_rule->flags & NL80211_RRF_NO_IR)) 191 if (ch->flags & IEEE80211_CHAN_NO_IR) 192 ch->flags &= ~IEEE80211_CHAN_NO_IR; 193} 194 195static void ath_force_clear_no_ir_freq(struct wiphy *wiphy, u16 center_freq) 196{ 197 struct ieee80211_channel *ch; 198 199 ch = ieee80211_get_channel(wiphy, center_freq); 200 if (!ch) 201 return; 202 203 ath_force_clear_no_ir_chan(wiphy, ch); 204} 205 206static void ath_force_no_ir_chan(struct ieee80211_channel *ch) 207{ 208 ch->flags |= IEEE80211_CHAN_NO_IR; 209} 210 211static void ath_force_no_ir_freq(struct wiphy *wiphy, u16 center_freq) 212{ 213 struct ieee80211_channel *ch; 214 215 ch = ieee80211_get_channel(wiphy, center_freq); 216 if (!ch) 217 return; 218 219 ath_force_no_ir_chan(ch); 220} 221 222/* 223 * N.B: These exception rules do not apply radar freqs. 224 * 225 * - We enable adhoc (or beaconing) if allowed by 11d 226 * - We enable active scan if the channel is allowed by 11d 227 * - If no country IE has been processed and a we determine we have 228 * received a beacon on a channel we can enable active scan and 229 * adhoc (or beaconing). 230 */ 231static void 232ath_reg_apply_beaconing_flags(struct wiphy *wiphy, 233 enum nl80211_reg_initiator initiator) 234{ 235 enum ieee80211_band band; 236 struct ieee80211_supported_band *sband; 237 const struct ieee80211_reg_rule *reg_rule; 238 struct ieee80211_channel *ch; 239 unsigned int i; 240 241 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 242 243 if (!wiphy->bands[band]) 244 continue; 245 246 sband = wiphy->bands[band]; 247 248 for (i = 0; i < sband->n_channels; i++) { 249 250 ch = &sband->channels[i]; 251 252 if (ath_is_radar_freq(ch->center_freq) || 253 (ch->flags & IEEE80211_CHAN_RADAR)) 254 continue; 255 256 if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { 257 reg_rule = freq_reg_info(wiphy, ch->center_freq); 258 if (IS_ERR(reg_rule)) 259 continue; 260 /* 261 * If 11d had a rule for this channel ensure 262 * we enable adhoc/beaconing if it allows us to 263 * use it. Note that we would have disabled it 264 * by applying our static world regdomain by 265 * default during init, prior to calling our 266 * regulatory_hint(). 267 */ 268 if (!(reg_rule->flags & NL80211_RRF_NO_IR)) 269 ch->flags &= ~IEEE80211_CHAN_NO_IR; 270 } else { 271 if (ch->beacon_found) 272 ch->flags &= ~IEEE80211_CHAN_NO_IR; 273 } 274 } 275 } 276 277} 278 279/** 280 * ath_reg_apply_active_scan_flags() 281 * @wiphy: the wiphy to use 282 * @initiator: the regulatory hint initiator 283 * 284 * If no country IE has been received always enable passive scan 285 * and no-ibss on these channels. This is only done for specific 286 * regulatory SKUs. 287 * 288 * If a country IE has been received check its rule for this 289 * channel first before enabling active scan. The passive scan 290 * would have been enforced by the initial processing of our 291 * custom regulatory domain. 292 */ 293static void 294ath_reg_apply_active_scan_flags(struct wiphy *wiphy, 295 enum nl80211_reg_initiator initiator) 296{ 297 struct ieee80211_supported_band *sband; 298 299 sband = wiphy->bands[IEEE80211_BAND_2GHZ]; 300 if (!sband) 301 return; 302 303 switch(initiator) { 304 case NL80211_REGDOM_SET_BY_COUNTRY_IE: 305 ath_force_clear_no_ir_freq(wiphy, 2467); 306 ath_force_clear_no_ir_freq(wiphy, 2472); 307 break; 308 default: 309 ath_force_no_ir_freq(wiphy, 2467); 310 ath_force_no_ir_freq(wiphy, 2472); 311 } 312} 313 314/* Always apply Radar/DFS rules on freq range 5260 MHz - 5700 MHz */ 315static void ath_reg_apply_radar_flags(struct wiphy *wiphy) 316{ 317 struct ieee80211_supported_band *sband; 318 struct ieee80211_channel *ch; 319 unsigned int i; 320 321 if (!wiphy->bands[IEEE80211_BAND_5GHZ]) 322 return; 323 324 sband = wiphy->bands[IEEE80211_BAND_5GHZ]; 325 326 for (i = 0; i < sband->n_channels; i++) { 327 ch = &sband->channels[i]; 328 if (!ath_is_radar_freq(ch->center_freq)) 329 continue; 330 /* We always enable radar detection/DFS on this 331 * frequency range. Additionally we also apply on 332 * this frequency range: 333 * - If STA mode does not yet have DFS supports disable 334 * active scanning 335 * - If adhoc mode does not support DFS yet then 336 * disable adhoc in the frequency. 337 * - If AP mode does not yet support radar detection/DFS 338 * do not allow AP mode 339 */ 340 if (!(ch->flags & IEEE80211_CHAN_DISABLED)) 341 ch->flags |= IEEE80211_CHAN_RADAR | 342 IEEE80211_CHAN_NO_IR; 343 } 344} 345 346static void ath_reg_apply_world_flags(struct wiphy *wiphy, 347 enum nl80211_reg_initiator initiator, 348 struct ath_regulatory *reg) 349{ 350 switch (reg->regpair->regDmnEnum) { 351 case 0x60: 352 case 0x63: 353 case 0x66: 354 case 0x67: 355 case 0x6C: 356 ath_reg_apply_beaconing_flags(wiphy, initiator); 357 break; 358 case 0x68: 359 ath_reg_apply_beaconing_flags(wiphy, initiator); 360 ath_reg_apply_active_scan_flags(wiphy, initiator); 361 break; 362 } 363} 364 365static u16 ath_regd_find_country_by_name(char *alpha2) 366{ 367 unsigned int i; 368 369 for (i = 0; i < ARRAY_SIZE(allCountries); i++) { 370 if (!memcmp(allCountries[i].isoName, alpha2, 2)) 371 return allCountries[i].countryCode; 372 } 373 374 return -1; 375} 376 377static int __ath_reg_dyn_country(struct wiphy *wiphy, 378 struct ath_regulatory *reg, 379 struct regulatory_request *request) 380{ 381 u16 country_code; 382 383 if (request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE && 384 !ath_is_world_regd(reg)) 385 return -EINVAL; 386 387 country_code = ath_regd_find_country_by_name(request->alpha2); 388 if (country_code == (u16) -1) 389 return -EINVAL; 390 391 reg->current_rd = COUNTRY_ERD_FLAG; 392 reg->current_rd |= country_code; 393 394 __ath_regd_init(reg); 395 396 ath_reg_apply_world_flags(wiphy, request->initiator, reg); 397 398 return 0; 399} 400 401static void ath_reg_dyn_country(struct wiphy *wiphy, 402 struct ath_regulatory *reg, 403 struct regulatory_request *request) 404{ 405 if (__ath_reg_dyn_country(wiphy, reg, request)) 406 return; 407 408 printk(KERN_DEBUG "ath: regdomain 0x%0x " 409 "dynamically updated by %s\n", 410 reg->current_rd, 411 reg_initiator_name(request->initiator)); 412} 413 414static bool dynamic_country_user_possible(struct ath_regulatory *reg) 415{ 416 if (config_enabled(CONFIG_ATH_REG_DYNAMIC_USER_CERT_TESTING)) 417 return true; 418 419 switch (reg->country_code) { 420 case CTRY_UNITED_STATES: 421 case CTRY_JAPAN1: 422 case CTRY_JAPAN2: 423 case CTRY_JAPAN3: 424 case CTRY_JAPAN4: 425 case CTRY_JAPAN5: 426 case CTRY_JAPAN6: 427 case CTRY_JAPAN7: 428 case CTRY_JAPAN8: 429 case CTRY_JAPAN9: 430 case CTRY_JAPAN10: 431 case CTRY_JAPAN11: 432 case CTRY_JAPAN12: 433 case CTRY_JAPAN13: 434 case CTRY_JAPAN14: 435 case CTRY_JAPAN15: 436 case CTRY_JAPAN16: 437 case CTRY_JAPAN17: 438 case CTRY_JAPAN18: 439 case CTRY_JAPAN19: 440 case CTRY_JAPAN20: 441 case CTRY_JAPAN21: 442 case CTRY_JAPAN22: 443 case CTRY_JAPAN23: 444 case CTRY_JAPAN24: 445 case CTRY_JAPAN25: 446 case CTRY_JAPAN26: 447 case CTRY_JAPAN27: 448 case CTRY_JAPAN28: 449 case CTRY_JAPAN29: 450 case CTRY_JAPAN30: 451 case CTRY_JAPAN31: 452 case CTRY_JAPAN32: 453 case CTRY_JAPAN33: 454 case CTRY_JAPAN34: 455 case CTRY_JAPAN35: 456 case CTRY_JAPAN36: 457 case CTRY_JAPAN37: 458 case CTRY_JAPAN38: 459 case CTRY_JAPAN39: 460 case CTRY_JAPAN40: 461 case CTRY_JAPAN41: 462 case CTRY_JAPAN42: 463 case CTRY_JAPAN43: 464 case CTRY_JAPAN44: 465 case CTRY_JAPAN45: 466 case CTRY_JAPAN46: 467 case CTRY_JAPAN47: 468 case CTRY_JAPAN48: 469 case CTRY_JAPAN49: 470 case CTRY_JAPAN50: 471 case CTRY_JAPAN51: 472 case CTRY_JAPAN52: 473 case CTRY_JAPAN53: 474 case CTRY_JAPAN54: 475 case CTRY_JAPAN55: 476 case CTRY_JAPAN56: 477 case CTRY_JAPAN57: 478 case CTRY_JAPAN58: 479 case CTRY_JAPAN59: 480 return false; 481 } 482 483 return true; 484} 485 486static void ath_reg_dyn_country_user(struct wiphy *wiphy, 487 struct ath_regulatory *reg, 488 struct regulatory_request *request) 489{ 490 if (!config_enabled(CONFIG_ATH_REG_DYNAMIC_USER_REG_HINTS)) 491 return; 492 if (!dynamic_country_user_possible(reg)) 493 return; 494 ath_reg_dyn_country(wiphy, reg, request); 495} 496 497void ath_reg_notifier_apply(struct wiphy *wiphy, 498 struct regulatory_request *request, 499 struct ath_regulatory *reg) 500{ 501 struct ath_common *common = container_of(reg, struct ath_common, 502 regulatory); 503 /* We always apply this */ 504 ath_reg_apply_radar_flags(wiphy); 505 506 /* 507 * This would happen when we have sent a custom regulatory request 508 * a world regulatory domain and the scheduler hasn't yet processed 509 * any pending requests in the queue. 510 */ 511 if (!request) 512 return; 513 514 switch (request->initiator) { 515 case NL80211_REGDOM_SET_BY_CORE: 516 /* 517 * If common->reg_world_copy is world roaming it means we *were* 518 * world roaming... so we now have to restore that data. 519 */ 520 if (!ath_is_world_regd(&common->reg_world_copy)) 521 break; 522 523 memcpy(reg, &common->reg_world_copy, 524 sizeof(struct ath_regulatory)); 525 break; 526 case NL80211_REGDOM_SET_BY_DRIVER: 527 break; 528 case NL80211_REGDOM_SET_BY_USER: 529 ath_reg_dyn_country_user(wiphy, reg, request); 530 break; 531 case NL80211_REGDOM_SET_BY_COUNTRY_IE: 532 ath_reg_dyn_country(wiphy, reg, request); 533 break; 534 } 535} 536EXPORT_SYMBOL(ath_reg_notifier_apply); 537 538static bool ath_regd_is_eeprom_valid(struct ath_regulatory *reg) 539{ 540 u16 rd = ath_regd_get_eepromRD(reg); 541 int i; 542 543 if (rd & COUNTRY_ERD_FLAG) { 544 /* EEPROM value is a country code */ 545 u16 cc = rd & ~COUNTRY_ERD_FLAG; 546 printk(KERN_DEBUG 547 "ath: EEPROM indicates we should expect " 548 "a country code\n"); 549 for (i = 0; i < ARRAY_SIZE(allCountries); i++) 550 if (allCountries[i].countryCode == cc) 551 return true; 552 } else { 553 /* EEPROM value is a regpair value */ 554 if (rd != CTRY_DEFAULT) 555 printk(KERN_DEBUG "ath: EEPROM indicates we " 556 "should expect a direct regpair map\n"); 557 for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) 558 if (regDomainPairs[i].regDmnEnum == rd) 559 return true; 560 } 561 printk(KERN_DEBUG 562 "ath: invalid regulatory domain/country code 0x%x\n", rd); 563 return false; 564} 565 566/* EEPROM country code to regpair mapping */ 567static struct country_code_to_enum_rd* 568ath_regd_find_country(u16 countryCode) 569{ 570 int i; 571 572 for (i = 0; i < ARRAY_SIZE(allCountries); i++) { 573 if (allCountries[i].countryCode == countryCode) 574 return &allCountries[i]; 575 } 576 return NULL; 577} 578 579/* EEPROM rd code to regpair mapping */ 580static struct country_code_to_enum_rd* 581ath_regd_find_country_by_rd(int regdmn) 582{ 583 int i; 584 585 for (i = 0; i < ARRAY_SIZE(allCountries); i++) { 586 if (allCountries[i].regDmnEnum == regdmn) 587 return &allCountries[i]; 588 } 589 return NULL; 590} 591 592/* Returns the map of the EEPROM set RD to a country code */ 593static u16 ath_regd_get_default_country(u16 rd) 594{ 595 if (rd & COUNTRY_ERD_FLAG) { 596 struct country_code_to_enum_rd *country = NULL; 597 u16 cc = rd & ~COUNTRY_ERD_FLAG; 598 599 country = ath_regd_find_country(cc); 600 if (country != NULL) 601 return cc; 602 } 603 604 return CTRY_DEFAULT; 605} 606 607static struct reg_dmn_pair_mapping* 608ath_get_regpair(int regdmn) 609{ 610 int i; 611 612 if (regdmn == NO_ENUMRD) 613 return NULL; 614 for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) { 615 if (regDomainPairs[i].regDmnEnum == regdmn) 616 return ®DomainPairs[i]; 617 } 618 return NULL; 619} 620 621static int 622ath_regd_init_wiphy(struct ath_regulatory *reg, 623 struct wiphy *wiphy, 624 void (*reg_notifier)(struct wiphy *wiphy, 625 struct regulatory_request *request)) 626{ 627 const struct ieee80211_regdomain *regd; 628 629 wiphy->reg_notifier = reg_notifier; 630 wiphy->regulatory_flags |= REGULATORY_STRICT_REG; 631 632 if (ath_is_world_regd(reg)) { 633 /* 634 * Anything applied here (prior to wiphy registration) gets 635 * saved on the wiphy orig_* parameters 636 */ 637 regd = ath_world_regdomain(reg); 638 wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG | 639 REGULATORY_COUNTRY_IE_FOLLOW_POWER; 640 } else { 641 /* 642 * This gets applied in the case of the absence of CRDA, 643 * it's our own custom world regulatory domain, similar to 644 * cfg80211's but we enable passive scanning. 645 */ 646 regd = ath_default_world_regdomain(); 647 } 648 wiphy_apply_custom_regulatory(wiphy, regd); 649 ath_reg_apply_radar_flags(wiphy); 650 ath_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg); 651 return 0; 652} 653 654/* 655 * Some users have reported their EEPROM programmed with 656 * 0x8000 set, this is not a supported regulatory domain 657 * but since we have more than one user with it we need 658 * a solution for them. We default to 0x64, which is the 659 * default Atheros world regulatory domain. 660 */ 661static void ath_regd_sanitize(struct ath_regulatory *reg) 662{ 663 if (reg->current_rd != COUNTRY_ERD_FLAG) 664 return; 665 printk(KERN_DEBUG "ath: EEPROM regdomain sanitized\n"); 666 reg->current_rd = 0x64; 667} 668 669static int __ath_regd_init(struct ath_regulatory *reg) 670{ 671 struct country_code_to_enum_rd *country = NULL; 672 u16 regdmn; 673 674 if (!reg) 675 return -EINVAL; 676 677 ath_regd_sanitize(reg); 678 679 printk(KERN_DEBUG "ath: EEPROM regdomain: 0x%0x\n", reg->current_rd); 680 681 if (!ath_regd_is_eeprom_valid(reg)) { 682 pr_err("Invalid EEPROM contents\n"); 683 return -EINVAL; 684 } 685 686 regdmn = ath_regd_get_eepromRD(reg); 687 reg->country_code = ath_regd_get_default_country(regdmn); 688 689 if (reg->country_code == CTRY_DEFAULT && 690 regdmn == CTRY_DEFAULT) { 691 printk(KERN_DEBUG "ath: EEPROM indicates default " 692 "country code should be used\n"); 693 reg->country_code = CTRY_UNITED_STATES; 694 } 695 696 if (reg->country_code == CTRY_DEFAULT) { 697 country = NULL; 698 } else { 699 printk(KERN_DEBUG "ath: doing EEPROM country->regdmn " 700 "map search\n"); 701 country = ath_regd_find_country(reg->country_code); 702 if (country == NULL) { 703 printk(KERN_DEBUG 704 "ath: no valid country maps found for " 705 "country code: 0x%0x\n", 706 reg->country_code); 707 return -EINVAL; 708 } else { 709 regdmn = country->regDmnEnum; 710 printk(KERN_DEBUG "ath: country maps to " 711 "regdmn code: 0x%0x\n", 712 regdmn); 713 } 714 } 715 716 reg->regpair = ath_get_regpair(regdmn); 717 718 if (!reg->regpair) { 719 printk(KERN_DEBUG "ath: " 720 "No regulatory domain pair found, cannot continue\n"); 721 return -EINVAL; 722 } 723 724 if (!country) 725 country = ath_regd_find_country_by_rd(regdmn); 726 727 if (country) { 728 reg->alpha2[0] = country->isoName[0]; 729 reg->alpha2[1] = country->isoName[1]; 730 } else { 731 reg->alpha2[0] = '0'; 732 reg->alpha2[1] = '0'; 733 } 734 735 printk(KERN_DEBUG "ath: Country alpha2 being used: %c%c\n", 736 reg->alpha2[0], reg->alpha2[1]); 737 printk(KERN_DEBUG "ath: Regpair used: 0x%0x\n", 738 reg->regpair->regDmnEnum); 739 740 return 0; 741} 742 743int 744ath_regd_init(struct ath_regulatory *reg, 745 struct wiphy *wiphy, 746 void (*reg_notifier)(struct wiphy *wiphy, 747 struct regulatory_request *request)) 748{ 749 struct ath_common *common = container_of(reg, struct ath_common, 750 regulatory); 751 int r; 752 753 r = __ath_regd_init(reg); 754 if (r) 755 return r; 756 757 if (ath_is_world_regd(reg)) 758 memcpy(&common->reg_world_copy, reg, 759 sizeof(struct ath_regulatory)); 760 761 ath_regd_init_wiphy(reg, wiphy, reg_notifier); 762 763 return 0; 764} 765EXPORT_SYMBOL(ath_regd_init); 766 767u32 ath_regd_get_band_ctl(struct ath_regulatory *reg, 768 enum ieee80211_band band) 769{ 770 if (!reg->regpair || 771 (reg->country_code == CTRY_DEFAULT && 772 is_wwr_sku(ath_regd_get_eepromRD(reg)))) { 773 return SD_NO_CTL; 774 } 775 776 switch (band) { 777 case IEEE80211_BAND_2GHZ: 778 return reg->regpair->reg_2ghz_ctl; 779 case IEEE80211_BAND_5GHZ: 780 return reg->regpair->reg_5ghz_ctl; 781 default: 782 return NO_CTL; 783 } 784} 785EXPORT_SYMBOL(ath_regd_get_band_ctl); 786