regd.c revision 8fe02e167efa8ed4a4503a5eedc0f49fcb7e3eb9
140c6d8aee40e373db75e6b0b4230fc8e8259d7a6Sascha Hauer/* 2285f5fa7e9a35e75d9022f9b036ed709721c5cdfDan Williams * Copyright (c) 2008-2009 Atheros Communications Inc. 3285f5fa7e9a35e75d9022f9b036ed709721c5cdfDan Williams * 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 181/* 182 * N.B: These exception rules do not apply radar freqs. 183 * 184 * - We enable adhoc (or beaconing) if allowed by 11d 185 * - We enable active scan if the channel is allowed by 11d 186 * - If no country IE has been processed and a we determine we have 187 * received a beacon on a channel we can enable active scan and 188 * adhoc (or beaconing). 189 */ 190static void 191ath_reg_apply_beaconing_flags(struct wiphy *wiphy, 192 enum nl80211_reg_initiator initiator) 193{ 194 enum ieee80211_band band; 195 struct ieee80211_supported_band *sband; 196 const struct ieee80211_reg_rule *reg_rule; 197 struct ieee80211_channel *ch; 198 unsigned int i; 199 200 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 201 202 if (!wiphy->bands[band]) 203 continue; 204 205 sband = wiphy->bands[band]; 206 207 for (i = 0; i < sband->n_channels; i++) { 208 209 ch = &sband->channels[i]; 210 211 if (ath_is_radar_freq(ch->center_freq) || 212 (ch->flags & IEEE80211_CHAN_RADAR)) 213 continue; 214 215 if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { 216 reg_rule = freq_reg_info(wiphy, ch->center_freq); 217 if (IS_ERR(reg_rule)) 218 continue; 219 /* 220 * If 11d had a rule for this channel ensure 221 * we enable adhoc/beaconing if it allows us to 222 * use it. Note that we would have disabled it 223 * by applying our static world regdomain by 224 * default during init, prior to calling our 225 * regulatory_hint(). 226 */ 227 if (!(reg_rule->flags & NL80211_RRF_NO_IR)) 228 ch->flags &= ~IEEE80211_CHAN_NO_IR; 229 } else { 230 if (ch->beacon_found) 231 ch->flags &= ~IEEE80211_CHAN_NO_IR; 232 } 233 } 234 } 235 236} 237 238/* Allows active scan scan on Ch 12 and 13 */ 239static void 240ath_reg_apply_active_scan_flags(struct wiphy *wiphy, 241 enum nl80211_reg_initiator initiator) 242{ 243 struct ieee80211_supported_band *sband; 244 struct ieee80211_channel *ch; 245 const struct ieee80211_reg_rule *reg_rule; 246 247 sband = wiphy->bands[IEEE80211_BAND_2GHZ]; 248 if (!sband) 249 return; 250 251 /* 252 * If no country IE has been received always enable active scan 253 * on these channels. This is only done for specific regulatory SKUs 254 */ 255 if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { 256 ch = &sband->channels[11]; /* CH 12 */ 257 if (ch->flags & IEEE80211_CHAN_NO_IR) 258 ch->flags &= ~IEEE80211_CHAN_NO_IR; 259 ch = &sband->channels[12]; /* CH 13 */ 260 if (ch->flags & IEEE80211_CHAN_NO_IR) 261 ch->flags &= ~IEEE80211_CHAN_NO_IR; 262 return; 263 } 264 265 /* 266 * If a country IE has been received check its rule for this 267 * channel first before enabling active scan. The passive scan 268 * would have been enforced by the initial processing of our 269 * custom regulatory domain. 270 */ 271 272 ch = &sband->channels[11]; /* CH 12 */ 273 reg_rule = freq_reg_info(wiphy, ch->center_freq); 274 if (!IS_ERR(reg_rule)) { 275 if (!(reg_rule->flags & NL80211_RRF_NO_IR)) 276 if (ch->flags & IEEE80211_CHAN_NO_IR) 277 ch->flags &= ~IEEE80211_CHAN_NO_IR; 278 } 279 280 ch = &sband->channels[12]; /* CH 13 */ 281 reg_rule = freq_reg_info(wiphy, ch->center_freq); 282 if (!IS_ERR(reg_rule)) { 283 if (!(reg_rule->flags & NL80211_RRF_NO_IR)) 284 if (ch->flags & IEEE80211_CHAN_NO_IR) 285 ch->flags &= ~IEEE80211_CHAN_NO_IR; 286 } 287} 288 289/* Always apply Radar/DFS rules on freq range 5260 MHz - 5700 MHz */ 290static void ath_reg_apply_radar_flags(struct wiphy *wiphy) 291{ 292 struct ieee80211_supported_band *sband; 293 struct ieee80211_channel *ch; 294 unsigned int i; 295 296 if (!wiphy->bands[IEEE80211_BAND_5GHZ]) 297 return; 298 299 sband = wiphy->bands[IEEE80211_BAND_5GHZ]; 300 301 for (i = 0; i < sband->n_channels; i++) { 302 ch = &sband->channels[i]; 303 if (!ath_is_radar_freq(ch->center_freq)) 304 continue; 305 /* We always enable radar detection/DFS on this 306 * frequency range. Additionally we also apply on 307 * this frequency range: 308 * - If STA mode does not yet have DFS supports disable 309 * active scanning 310 * - If adhoc mode does not support DFS yet then 311 * disable adhoc in the frequency. 312 * - If AP mode does not yet support radar detection/DFS 313 * do not allow AP mode 314 */ 315 if (!(ch->flags & IEEE80211_CHAN_DISABLED)) 316 ch->flags |= IEEE80211_CHAN_RADAR | 317 IEEE80211_CHAN_NO_IR; 318 } 319} 320 321static void ath_reg_apply_world_flags(struct wiphy *wiphy, 322 enum nl80211_reg_initiator initiator, 323 struct ath_regulatory *reg) 324{ 325 switch (reg->regpair->regDmnEnum) { 326 case 0x60: 327 case 0x63: 328 case 0x66: 329 case 0x67: 330 case 0x6C: 331 ath_reg_apply_beaconing_flags(wiphy, initiator); 332 break; 333 case 0x68: 334 ath_reg_apply_beaconing_flags(wiphy, initiator); 335 ath_reg_apply_active_scan_flags(wiphy, initiator); 336 break; 337 } 338} 339 340static u16 ath_regd_find_country_by_name(char *alpha2) 341{ 342 unsigned int i; 343 344 for (i = 0; i < ARRAY_SIZE(allCountries); i++) { 345 if (!memcmp(allCountries[i].isoName, alpha2, 2)) 346 return allCountries[i].countryCode; 347 } 348 349 return -1; 350} 351 352static int __ath_reg_dyn_country(struct wiphy *wiphy, 353 struct ath_regulatory *reg, 354 struct regulatory_request *request) 355{ 356 u16 country_code; 357 358 if (!ath_is_world_regd(reg)) 359 return -EINVAL; 360 361 country_code = ath_regd_find_country_by_name(request->alpha2); 362 if (country_code == (u16) -1) 363 return -EINVAL; 364 365 reg->current_rd = COUNTRY_ERD_FLAG; 366 reg->current_rd |= country_code; 367 368 __ath_regd_init(reg); 369 370 ath_reg_apply_world_flags(wiphy, request->initiator, reg); 371 372 return 0; 373} 374 375static void ath_reg_dyn_country(struct wiphy *wiphy, 376 struct ath_regulatory *reg, 377 struct regulatory_request *request) 378{ 379 if (__ath_reg_dyn_country(wiphy, reg, request)) 380 return; 381 382 printk(KERN_DEBUG "ath: regdomain 0x%0x " 383 "dynamically updated by %s\n", 384 reg->current_rd, 385 reg_initiator_name(request->initiator)); 386} 387 388static bool dynamic_country_user_possible(struct ath_regulatory *reg) 389{ 390 if (config_enabled(CONFIG_ATH_REG_DYNAMIC_USER_CERT_TESTING)) 391 return true; 392 393 switch (reg->country_code) { 394 case CTRY_UNITED_STATES: 395 case CTRY_JAPAN1: 396 case CTRY_JAPAN2: 397 case CTRY_JAPAN3: 398 case CTRY_JAPAN4: 399 case CTRY_JAPAN5: 400 case CTRY_JAPAN6: 401 case CTRY_JAPAN7: 402 case CTRY_JAPAN8: 403 case CTRY_JAPAN9: 404 case CTRY_JAPAN10: 405 case CTRY_JAPAN11: 406 case CTRY_JAPAN12: 407 case CTRY_JAPAN13: 408 case CTRY_JAPAN14: 409 case CTRY_JAPAN15: 410 case CTRY_JAPAN16: 411 case CTRY_JAPAN17: 412 case CTRY_JAPAN18: 413 case CTRY_JAPAN19: 414 case CTRY_JAPAN20: 415 case CTRY_JAPAN21: 416 case CTRY_JAPAN22: 417 case CTRY_JAPAN23: 418 case CTRY_JAPAN24: 419 case CTRY_JAPAN25: 420 case CTRY_JAPAN26: 421 case CTRY_JAPAN27: 422 case CTRY_JAPAN28: 423 case CTRY_JAPAN29: 424 case CTRY_JAPAN30: 425 case CTRY_JAPAN31: 426 case CTRY_JAPAN32: 427 case CTRY_JAPAN33: 428 case CTRY_JAPAN34: 429 case CTRY_JAPAN35: 430 case CTRY_JAPAN36: 431 case CTRY_JAPAN37: 432 case CTRY_JAPAN38: 433 case CTRY_JAPAN39: 434 case CTRY_JAPAN40: 435 case CTRY_JAPAN41: 436 case CTRY_JAPAN42: 437 case CTRY_JAPAN43: 438 case CTRY_JAPAN44: 439 case CTRY_JAPAN45: 440 case CTRY_JAPAN46: 441 case CTRY_JAPAN47: 442 case CTRY_JAPAN48: 443 case CTRY_JAPAN49: 444 case CTRY_JAPAN50: 445 case CTRY_JAPAN51: 446 case CTRY_JAPAN52: 447 case CTRY_JAPAN53: 448 case CTRY_JAPAN54: 449 case CTRY_JAPAN55: 450 case CTRY_JAPAN56: 451 case CTRY_JAPAN57: 452 case CTRY_JAPAN58: 453 case CTRY_JAPAN59: 454 return false; 455 } 456 457 return true; 458} 459 460static void ath_reg_dyn_country_user(struct wiphy *wiphy, 461 struct ath_regulatory *reg, 462 struct regulatory_request *request) 463{ 464 if (!config_enabled(CONFIG_ATH_REG_DYNAMIC_USER_REG_HINTS)) 465 return; 466 if (!dynamic_country_user_possible(reg)) 467 return; 468 ath_reg_dyn_country(wiphy, reg, request); 469} 470 471void ath_reg_notifier_apply(struct wiphy *wiphy, 472 struct regulatory_request *request, 473 struct ath_regulatory *reg) 474{ 475 struct ath_common *common = container_of(reg, struct ath_common, 476 regulatory); 477 /* We always apply this */ 478 ath_reg_apply_radar_flags(wiphy); 479 480 /* 481 * This would happen when we have sent a custom regulatory request 482 * a world regulatory domain and the scheduler hasn't yet processed 483 * any pending requests in the queue. 484 */ 485 if (!request) 486 return; 487 488 switch (request->initiator) { 489 case NL80211_REGDOM_SET_BY_CORE: 490 /* 491 * If common->reg_world_copy is world roaming it means we *were* 492 * world roaming... so we now have to restore that data. 493 */ 494 if (!ath_is_world_regd(&common->reg_world_copy)) 495 break; 496 497 memcpy(reg, &common->reg_world_copy, 498 sizeof(struct ath_regulatory)); 499 break; 500 case NL80211_REGDOM_SET_BY_DRIVER: 501 break; 502 case NL80211_REGDOM_SET_BY_USER: 503 ath_reg_dyn_country_user(wiphy, reg, request); 504 break; 505 case NL80211_REGDOM_SET_BY_COUNTRY_IE: 506 ath_reg_dyn_country(wiphy, reg, request); 507 break; 508 } 509} 510EXPORT_SYMBOL(ath_reg_notifier_apply); 511 512static bool ath_regd_is_eeprom_valid(struct ath_regulatory *reg) 513{ 514 u16 rd = ath_regd_get_eepromRD(reg); 515 int i; 516 517 if (rd & COUNTRY_ERD_FLAG) { 518 /* EEPROM value is a country code */ 519 u16 cc = rd & ~COUNTRY_ERD_FLAG; 520 printk(KERN_DEBUG 521 "ath: EEPROM indicates we should expect " 522 "a country code\n"); 523 for (i = 0; i < ARRAY_SIZE(allCountries); i++) 524 if (allCountries[i].countryCode == cc) 525 return true; 526 } else { 527 /* EEPROM value is a regpair value */ 528 if (rd != CTRY_DEFAULT) 529 printk(KERN_DEBUG "ath: EEPROM indicates we " 530 "should expect a direct regpair map\n"); 531 for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) 532 if (regDomainPairs[i].regDmnEnum == rd) 533 return true; 534 } 535 printk(KERN_DEBUG 536 "ath: invalid regulatory domain/country code 0x%x\n", rd); 537 return false; 538} 539 540/* EEPROM country code to regpair mapping */ 541static struct country_code_to_enum_rd* 542ath_regd_find_country(u16 countryCode) 543{ 544 int i; 545 546 for (i = 0; i < ARRAY_SIZE(allCountries); i++) { 547 if (allCountries[i].countryCode == countryCode) 548 return &allCountries[i]; 549 } 550 return NULL; 551} 552 553/* EEPROM rd code to regpair mapping */ 554static struct country_code_to_enum_rd* 555ath_regd_find_country_by_rd(int regdmn) 556{ 557 int i; 558 559 for (i = 0; i < ARRAY_SIZE(allCountries); i++) { 560 if (allCountries[i].regDmnEnum == regdmn) 561 return &allCountries[i]; 562 } 563 return NULL; 564} 565 566/* Returns the map of the EEPROM set RD to a country code */ 567static u16 ath_regd_get_default_country(u16 rd) 568{ 569 if (rd & COUNTRY_ERD_FLAG) { 570 struct country_code_to_enum_rd *country = NULL; 571 u16 cc = rd & ~COUNTRY_ERD_FLAG; 572 573 country = ath_regd_find_country(cc); 574 if (country != NULL) 575 return cc; 576 } 577 578 return CTRY_DEFAULT; 579} 580 581static struct reg_dmn_pair_mapping* 582ath_get_regpair(int regdmn) 583{ 584 int i; 585 586 if (regdmn == NO_ENUMRD) 587 return NULL; 588 for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) { 589 if (regDomainPairs[i].regDmnEnum == regdmn) 590 return ®DomainPairs[i]; 591 } 592 return NULL; 593} 594 595static int 596ath_regd_init_wiphy(struct ath_regulatory *reg, 597 struct wiphy *wiphy, 598 void (*reg_notifier)(struct wiphy *wiphy, 599 struct regulatory_request *request)) 600{ 601 const struct ieee80211_regdomain *regd; 602 603 wiphy->reg_notifier = reg_notifier; 604 wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY; 605 606 if (ath_is_world_regd(reg)) { 607 /* 608 * Anything applied here (prior to wiphy registration) gets 609 * saved on the wiphy orig_* parameters 610 */ 611 regd = ath_world_regdomain(reg); 612 wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; 613 } else { 614 /* 615 * This gets applied in the case of the absence of CRDA, 616 * it's our own custom world regulatory domain, similar to 617 * cfg80211's but we enable passive scanning. 618 */ 619 regd = ath_default_world_regdomain(); 620 } 621 wiphy_apply_custom_regulatory(wiphy, regd); 622 ath_reg_apply_radar_flags(wiphy); 623 ath_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg); 624 return 0; 625} 626 627/* 628 * Some users have reported their EEPROM programmed with 629 * 0x8000 set, this is not a supported regulatory domain 630 * but since we have more than one user with it we need 631 * a solution for them. We default to 0x64, which is the 632 * default Atheros world regulatory domain. 633 */ 634static void ath_regd_sanitize(struct ath_regulatory *reg) 635{ 636 if (reg->current_rd != COUNTRY_ERD_FLAG) 637 return; 638 printk(KERN_DEBUG "ath: EEPROM regdomain sanitized\n"); 639 reg->current_rd = 0x64; 640} 641 642static int __ath_regd_init(struct ath_regulatory *reg) 643{ 644 struct country_code_to_enum_rd *country = NULL; 645 u16 regdmn; 646 647 if (!reg) 648 return -EINVAL; 649 650 ath_regd_sanitize(reg); 651 652 printk(KERN_DEBUG "ath: EEPROM regdomain: 0x%0x\n", reg->current_rd); 653 654 if (!ath_regd_is_eeprom_valid(reg)) { 655 pr_err("Invalid EEPROM contents\n"); 656 return -EINVAL; 657 } 658 659 regdmn = ath_regd_get_eepromRD(reg); 660 reg->country_code = ath_regd_get_default_country(regdmn); 661 662 if (reg->country_code == CTRY_DEFAULT && 663 regdmn == CTRY_DEFAULT) { 664 printk(KERN_DEBUG "ath: EEPROM indicates default " 665 "country code should be used\n"); 666 reg->country_code = CTRY_UNITED_STATES; 667 } 668 669 if (reg->country_code == CTRY_DEFAULT) { 670 country = NULL; 671 } else { 672 printk(KERN_DEBUG "ath: doing EEPROM country->regdmn " 673 "map search\n"); 674 country = ath_regd_find_country(reg->country_code); 675 if (country == NULL) { 676 printk(KERN_DEBUG 677 "ath: no valid country maps found for " 678 "country code: 0x%0x\n", 679 reg->country_code); 680 return -EINVAL; 681 } else { 682 regdmn = country->regDmnEnum; 683 printk(KERN_DEBUG "ath: country maps to " 684 "regdmn code: 0x%0x\n", 685 regdmn); 686 } 687 } 688 689 reg->regpair = ath_get_regpair(regdmn); 690 691 if (!reg->regpair) { 692 printk(KERN_DEBUG "ath: " 693 "No regulatory domain pair found, cannot continue\n"); 694 return -EINVAL; 695 } 696 697 if (!country) 698 country = ath_regd_find_country_by_rd(regdmn); 699 700 if (country) { 701 reg->alpha2[0] = country->isoName[0]; 702 reg->alpha2[1] = country->isoName[1]; 703 } else { 704 reg->alpha2[0] = '0'; 705 reg->alpha2[1] = '0'; 706 } 707 708 printk(KERN_DEBUG "ath: Country alpha2 being used: %c%c\n", 709 reg->alpha2[0], reg->alpha2[1]); 710 printk(KERN_DEBUG "ath: Regpair used: 0x%0x\n", 711 reg->regpair->regDmnEnum); 712 713 return 0; 714} 715 716int 717ath_regd_init(struct ath_regulatory *reg, 718 struct wiphy *wiphy, 719 void (*reg_notifier)(struct wiphy *wiphy, 720 struct regulatory_request *request)) 721{ 722 struct ath_common *common = container_of(reg, struct ath_common, 723 regulatory); 724 int r; 725 726 r = __ath_regd_init(reg); 727 if (r) 728 return r; 729 730 if (ath_is_world_regd(reg)) 731 memcpy(&common->reg_world_copy, reg, 732 sizeof(struct ath_regulatory)); 733 734 ath_regd_init_wiphy(reg, wiphy, reg_notifier); 735 736 return 0; 737} 738EXPORT_SYMBOL(ath_regd_init); 739 740u32 ath_regd_get_band_ctl(struct ath_regulatory *reg, 741 enum ieee80211_band band) 742{ 743 if (!reg->regpair || 744 (reg->country_code == CTRY_DEFAULT && 745 is_wwr_sku(ath_regd_get_eepromRD(reg)))) { 746 return SD_NO_CTL; 747 } 748 749 switch (band) { 750 case IEEE80211_BAND_2GHZ: 751 return reg->regpair->reg_2ghz_ctl; 752 case IEEE80211_BAND_5GHZ: 753 return reg->regpair->reg_5ghz_ctl; 754 default: 755 return NO_CTL; 756 } 757} 758EXPORT_SYMBOL(ath_regd_get_band_ctl); 759