linux/drivers/net/wireless/ath/regd.c
<<
>>
Prefs
   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#include <linux/kernel.h>
  18#include <linux/slab.h>
  19#include <net/cfg80211.h>
  20#include <net/mac80211.h>
  21#include "regd.h"
  22#include "regd_common.h"
  23
  24/*
  25 * This is a set of common rules used by our world regulatory domains.
  26 * We have 12 world regulatory domains. To save space we consolidate
  27 * the regulatory domains in 5 structures by frequency and change
  28 * the flags on our reg_notifier() on a case by case basis.
  29 */
  30
  31/* Only these channels all allow active scan on all world regulatory domains */
  32#define ATH9K_2GHZ_CH01_11      REG_RULE(2412-10, 2462+10, 40, 0, 20, 0)
  33
  34/* We enable active scan on these a case by case basis by regulatory domain */
  35#define ATH9K_2GHZ_CH12_13      REG_RULE(2467-10, 2472+10, 40, 0, 20,\
  36                                        NL80211_RRF_PASSIVE_SCAN)
  37#define ATH9K_2GHZ_CH14         REG_RULE(2484-10, 2484+10, 40, 0, 20,\
  38                                NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM)
  39
  40/* We allow IBSS on these on a case by case basis by regulatory domain */
  41#define ATH9K_5GHZ_5150_5350    REG_RULE(5150-10, 5350+10, 40, 0, 30,\
  42                                NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
  43#define ATH9K_5GHZ_5470_5850    REG_RULE(5470-10, 5850+10, 40, 0, 30,\
  44                                NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
  45#define ATH9K_5GHZ_5725_5850    REG_RULE(5725-10, 5850+10, 40, 0, 30,\
  46                                NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
  47
  48#define ATH9K_2GHZ_ALL          ATH9K_2GHZ_CH01_11, \
  49                                ATH9K_2GHZ_CH12_13, \
  50                                ATH9K_2GHZ_CH14
  51
  52#define ATH9K_5GHZ_ALL          ATH9K_5GHZ_5150_5350, \
  53                                ATH9K_5GHZ_5470_5850
  54/* This one skips what we call "mid band" */
  55#define ATH9K_5GHZ_NO_MIDBAND   ATH9K_5GHZ_5150_5350, \
  56                                ATH9K_5GHZ_5725_5850
  57
  58/* Can be used for:
  59 * 0x60, 0x61, 0x62 */
  60static const struct ieee80211_regdomain ath_world_regdom_60_61_62 = {
  61        .n_reg_rules = 5,
  62        .alpha2 =  "99",
  63        .reg_rules = {
  64                ATH9K_2GHZ_ALL,
  65                ATH9K_5GHZ_ALL,
  66        }
  67};
  68
  69/* Can be used by 0x63 and 0x65 */
  70static const struct ieee80211_regdomain ath_world_regdom_63_65 = {
  71        .n_reg_rules = 4,
  72        .alpha2 =  "99",
  73        .reg_rules = {
  74                ATH9K_2GHZ_CH01_11,
  75                ATH9K_2GHZ_CH12_13,
  76                ATH9K_5GHZ_NO_MIDBAND,
  77        }
  78};
  79
  80/* Can be used by 0x64 only */
  81static const struct ieee80211_regdomain ath_world_regdom_64 = {
  82        .n_reg_rules = 3,
  83        .alpha2 =  "99",
  84        .reg_rules = {
  85                ATH9K_2GHZ_CH01_11,
  86                ATH9K_5GHZ_NO_MIDBAND,
  87        }
  88};
  89
  90/* Can be used by 0x66 and 0x69 */
  91static const struct ieee80211_regdomain ath_world_regdom_66_69 = {
  92        .n_reg_rules = 3,
  93        .alpha2 =  "99",
  94        .reg_rules = {
  95                ATH9K_2GHZ_CH01_11,
  96                ATH9K_5GHZ_ALL,
  97        }
  98};
  99
 100/* Can be used by 0x67, 0x6A and 0x68 */
 101static const struct ieee80211_regdomain ath_world_regdom_67_68_6A = {
 102        .n_reg_rules = 4,
 103        .alpha2 =  "99",
 104        .reg_rules = {
 105                ATH9K_2GHZ_CH01_11,
 106                ATH9K_2GHZ_CH12_13,
 107                ATH9K_5GHZ_ALL,
 108        }
 109};
 110
 111static inline bool is_wwr_sku(u16 regd)
 112{
 113        return ((regd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX) ||
 114                (regd == WORLD);
 115}
 116
 117static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg)
 118{
 119        return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG;
 120}
 121
 122bool ath_is_world_regd(struct ath_regulatory *reg)
 123{
 124        return is_wwr_sku(ath_regd_get_eepromRD(reg));
 125}
 126EXPORT_SYMBOL(ath_is_world_regd);
 127
 128static const struct ieee80211_regdomain *ath_default_world_regdomain(void)
 129{
 130        /* this is the most restrictive */
 131        return &ath_world_regdom_64;
 132}
 133
 134static const struct
 135ieee80211_regdomain *ath_world_regdomain(struct ath_regulatory *reg)
 136{
 137        switch (reg->regpair->regDmnEnum) {
 138        case 0x60:
 139        case 0x61:
 140        case 0x62:
 141                return &ath_world_regdom_60_61_62;
 142        case 0x63:
 143        case 0x65:
 144                return &ath_world_regdom_63_65;
 145        case 0x64:
 146                return &ath_world_regdom_64;
 147        case 0x66:
 148        case 0x69:
 149                return &ath_world_regdom_66_69;
 150        case 0x67:
 151        case 0x68:
 152        case 0x6A:
 153                return &ath_world_regdom_67_68_6A;
 154        default:
 155                WARN_ON(1);
 156                return ath_default_world_regdomain();
 157        }
 158}
 159
 160/* Frequency is one where radar detection is required */
 161static bool ath_is_radar_freq(u16 center_freq)
 162{
 163        return (center_freq >= 5260 && center_freq <= 5700);
 164}
 165
 166/*
 167 * N.B: These exception rules do not apply radar freqs.
 168 *
 169 * - We enable adhoc (or beaconing) if allowed by 11d
 170 * - We enable active scan if the channel is allowed by 11d
 171 * - If no country IE has been processed and a we determine we have
 172 *   received a beacon on a channel we can enable active scan and
 173 *   adhoc (or beaconing).
 174 */
 175static void
 176ath_reg_apply_beaconing_flags(struct wiphy *wiphy,
 177                              enum nl80211_reg_initiator initiator)
 178{
 179        enum ieee80211_band band;
 180        struct ieee80211_supported_band *sband;
 181        const struct ieee80211_reg_rule *reg_rule;
 182        struct ieee80211_channel *ch;
 183        unsigned int i;
 184        u32 bandwidth = 0;
 185        int r;
 186
 187        for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
 188
 189                if (!wiphy->bands[band])
 190                        continue;
 191
 192                sband = wiphy->bands[band];
 193
 194                for (i = 0; i < sband->n_channels; i++) {
 195
 196                        ch = &sband->channels[i];
 197
 198                        if (ath_is_radar_freq(ch->center_freq) ||
 199                            (ch->flags & IEEE80211_CHAN_RADAR))
 200                                continue;
 201
 202                        if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
 203                                r = freq_reg_info(wiphy,
 204                                                  ch->center_freq,
 205                                                  bandwidth,
 206                                                  &reg_rule);
 207                                if (r)
 208                                        continue;
 209                                /*
 210                                 * If 11d had a rule for this channel ensure
 211                                 * we enable adhoc/beaconing if it allows us to
 212                                 * use it. Note that we would have disabled it
 213                                 * by applying our static world regdomain by
 214                                 * default during init, prior to calling our
 215                                 * regulatory_hint().
 216                                 */
 217                                if (!(reg_rule->flags &
 218                                    NL80211_RRF_NO_IBSS))
 219                                        ch->flags &=
 220                                          ~IEEE80211_CHAN_NO_IBSS;
 221                                if (!(reg_rule->flags &
 222                                    NL80211_RRF_PASSIVE_SCAN))
 223                                        ch->flags &=
 224                                          ~IEEE80211_CHAN_PASSIVE_SCAN;
 225                        } else {
 226                                if (ch->beacon_found)
 227                                        ch->flags &= ~(IEEE80211_CHAN_NO_IBSS |
 228                                          IEEE80211_CHAN_PASSIVE_SCAN);
 229                        }
 230                }
 231        }
 232
 233}
 234
 235/* Allows active scan scan on Ch 12 and 13 */
 236static void
 237ath_reg_apply_active_scan_flags(struct wiphy *wiphy,
 238                                enum nl80211_reg_initiator initiator)
 239{
 240        struct ieee80211_supported_band *sband;
 241        struct ieee80211_channel *ch;
 242        const struct ieee80211_reg_rule *reg_rule;
 243        u32 bandwidth = 0;
 244        int r;
 245
 246        sband = wiphy->bands[IEEE80211_BAND_2GHZ];
 247
 248        /*
 249         * If no country IE has been received always enable active scan
 250         * on these channels. This is only done for specific regulatory SKUs
 251         */
 252        if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
 253                ch = &sband->channels[11]; /* CH 12 */
 254                if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
 255                        ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
 256                ch = &sband->channels[12]; /* CH 13 */
 257                if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
 258                        ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
 259                return;
 260        }
 261
 262        /*
 263         * If a country IE has been recieved check its rule for this
 264         * channel first before enabling active scan. The passive scan
 265         * would have been enforced by the initial processing of our
 266         * custom regulatory domain.
 267         */
 268
 269        ch = &sband->channels[11]; /* CH 12 */
 270        r = freq_reg_info(wiphy, ch->center_freq, bandwidth, &reg_rule);
 271        if (!r) {
 272                if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
 273                        if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
 274                                ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
 275        }
 276
 277        ch = &sband->channels[12]; /* CH 13 */
 278        r = freq_reg_info(wiphy, ch->center_freq, bandwidth, &reg_rule);
 279        if (!r) {
 280                if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
 281                        if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
 282                                ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
 283        }
 284}
 285
 286/* Always apply Radar/DFS rules on freq range 5260 MHz - 5700 MHz */
 287static void ath_reg_apply_radar_flags(struct wiphy *wiphy)
 288{
 289        struct ieee80211_supported_band *sband;
 290        struct ieee80211_channel *ch;
 291        unsigned int i;
 292
 293        if (!wiphy->bands[IEEE80211_BAND_5GHZ])
 294                return;
 295
 296        sband = wiphy->bands[IEEE80211_BAND_5GHZ];
 297
 298        for (i = 0; i < sband->n_channels; i++) {
 299                ch = &sband->channels[i];
 300                if (!ath_is_radar_freq(ch->center_freq))
 301                        continue;
 302                /* We always enable radar detection/DFS on this
 303                 * frequency range. Additionally we also apply on
 304                 * this frequency range:
 305                 * - If STA mode does not yet have DFS supports disable
 306                 *   active scanning
 307                 * - If adhoc mode does not support DFS yet then
 308                 *   disable adhoc in the frequency.
 309                 * - If AP mode does not yet support radar detection/DFS
 310                 *   do not allow AP mode
 311                 */
 312                if (!(ch->flags & IEEE80211_CHAN_DISABLED))
 313                        ch->flags |= IEEE80211_CHAN_RADAR |
 314                                     IEEE80211_CHAN_NO_IBSS |
 315                                     IEEE80211_CHAN_PASSIVE_SCAN;
 316        }
 317}
 318
 319static void ath_reg_apply_world_flags(struct wiphy *wiphy,
 320                                      enum nl80211_reg_initiator initiator,
 321                                      struct ath_regulatory *reg)
 322{
 323        switch (reg->regpair->regDmnEnum) {
 324        case 0x60:
 325        case 0x63:
 326        case 0x66:
 327        case 0x67:
 328                ath_reg_apply_beaconing_flags(wiphy, initiator);
 329                break;
 330        case 0x68:
 331                ath_reg_apply_beaconing_flags(wiphy, initiator);
 332                ath_reg_apply_active_scan_flags(wiphy, initiator);
 333                break;
 334        }
 335        return;
 336}
 337
 338int ath_reg_notifier_apply(struct wiphy *wiphy,
 339                           struct regulatory_request *request,
 340                           struct ath_regulatory *reg)
 341{
 342        /* We always apply this */
 343        ath_reg_apply_radar_flags(wiphy);
 344
 345        switch (request->initiator) {
 346        case NL80211_REGDOM_SET_BY_DRIVER:
 347        case NL80211_REGDOM_SET_BY_CORE:
 348        case NL80211_REGDOM_SET_BY_USER:
 349                break;
 350        case NL80211_REGDOM_SET_BY_COUNTRY_IE:
 351                if (ath_is_world_regd(reg))
 352                        ath_reg_apply_world_flags(wiphy, request->initiator,
 353                                                  reg);
 354                break;
 355        }
 356
 357        return 0;
 358}
 359EXPORT_SYMBOL(ath_reg_notifier_apply);
 360
 361static bool ath_regd_is_eeprom_valid(struct ath_regulatory *reg)
 362{
 363         u16 rd = ath_regd_get_eepromRD(reg);
 364        int i;
 365
 366        if (rd & COUNTRY_ERD_FLAG) {
 367                /* EEPROM value is a country code */
 368                u16 cc = rd & ~COUNTRY_ERD_FLAG;
 369                printk(KERN_DEBUG
 370                       "ath: EEPROM indicates we should expect "
 371                        "a country code\n");
 372                for (i = 0; i < ARRAY_SIZE(allCountries); i++)
 373                        if (allCountries[i].countryCode == cc)
 374                                return true;
 375        } else {
 376                /* EEPROM value is a regpair value */
 377                if (rd != CTRY_DEFAULT)
 378                        printk(KERN_DEBUG "ath: EEPROM indicates we "
 379                               "should expect a direct regpair map\n");
 380                for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++)
 381                        if (regDomainPairs[i].regDmnEnum == rd)
 382                                return true;
 383        }
 384        printk(KERN_DEBUG
 385                 "ath: invalid regulatory domain/country code 0x%x\n", rd);
 386        return false;
 387}
 388
 389/* EEPROM country code to regpair mapping */
 390static struct country_code_to_enum_rd*
 391ath_regd_find_country(u16 countryCode)
 392{
 393        int i;
 394
 395        for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
 396                if (allCountries[i].countryCode == countryCode)
 397                        return &allCountries[i];
 398        }
 399        return NULL;
 400}
 401
 402/* EEPROM rd code to regpair mapping */
 403static struct country_code_to_enum_rd*
 404ath_regd_find_country_by_rd(int regdmn)
 405{
 406        int i;
 407
 408        for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
 409                if (allCountries[i].regDmnEnum == regdmn)
 410                        return &allCountries[i];
 411        }
 412        return NULL;
 413}
 414
 415/* Returns the map of the EEPROM set RD to a country code */
 416static u16 ath_regd_get_default_country(u16 rd)
 417{
 418        if (rd & COUNTRY_ERD_FLAG) {
 419                struct country_code_to_enum_rd *country = NULL;
 420                u16 cc = rd & ~COUNTRY_ERD_FLAG;
 421
 422                country = ath_regd_find_country(cc);
 423                if (country != NULL)
 424                        return cc;
 425        }
 426
 427        return CTRY_DEFAULT;
 428}
 429
 430static struct reg_dmn_pair_mapping*
 431ath_get_regpair(int regdmn)
 432{
 433        int i;
 434
 435        if (regdmn == NO_ENUMRD)
 436                return NULL;
 437        for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) {
 438                if (regDomainPairs[i].regDmnEnum == regdmn)
 439                        return &regDomainPairs[i];
 440        }
 441        return NULL;
 442}
 443
 444static int
 445ath_regd_init_wiphy(struct ath_regulatory *reg,
 446                    struct wiphy *wiphy,
 447                    int (*reg_notifier)(struct wiphy *wiphy,
 448                                        struct regulatory_request *request))
 449{
 450        const struct ieee80211_regdomain *regd;
 451
 452        wiphy->reg_notifier = reg_notifier;
 453        wiphy->strict_regulatory = true;
 454
 455        if (ath_is_world_regd(reg)) {
 456                /*
 457                 * Anything applied here (prior to wiphy registration) gets
 458                 * saved on the wiphy orig_* parameters
 459                 */
 460                regd = ath_world_regdomain(reg);
 461                wiphy->custom_regulatory = true;
 462                wiphy->strict_regulatory = false;
 463        } else {
 464                /*
 465                 * This gets applied in the case of the absense of CRDA,
 466                 * it's our own custom world regulatory domain, similar to
 467                 * cfg80211's but we enable passive scanning.
 468                 */
 469                regd = ath_default_world_regdomain();
 470        }
 471        wiphy_apply_custom_regulatory(wiphy, regd);
 472        ath_reg_apply_radar_flags(wiphy);
 473        ath_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg);
 474        return 0;
 475}
 476
 477/*
 478 * Some users have reported their EEPROM programmed with
 479 * 0x8000 set, this is not a supported regulatory domain
 480 * but since we have more than one user with it we need
 481 * a solution for them. We default to 0x64, which is the
 482 * default Atheros world regulatory domain.
 483 */
 484static void ath_regd_sanitize(struct ath_regulatory *reg)
 485{
 486        if (reg->current_rd != COUNTRY_ERD_FLAG)
 487                return;
 488        printk(KERN_DEBUG "ath: EEPROM regdomain sanitized\n");
 489        reg->current_rd = 0x64;
 490}
 491
 492int
 493ath_regd_init(struct ath_regulatory *reg,
 494              struct wiphy *wiphy,
 495              int (*reg_notifier)(struct wiphy *wiphy,
 496                                  struct regulatory_request *request))
 497{
 498        struct country_code_to_enum_rd *country = NULL;
 499        u16 regdmn;
 500
 501        if (!reg)
 502                return -EINVAL;
 503
 504        ath_regd_sanitize(reg);
 505
 506        printk(KERN_DEBUG "ath: EEPROM regdomain: 0x%0x\n", reg->current_rd);
 507
 508        if (!ath_regd_is_eeprom_valid(reg)) {
 509                printk(KERN_ERR "ath: Invalid EEPROM contents\n");
 510                return -EINVAL;
 511        }
 512
 513        regdmn = ath_regd_get_eepromRD(reg);
 514        reg->country_code = ath_regd_get_default_country(regdmn);
 515
 516        if (reg->country_code == CTRY_DEFAULT &&
 517            regdmn == CTRY_DEFAULT) {
 518                printk(KERN_DEBUG "ath: EEPROM indicates default "
 519                       "country code should be used\n");
 520                reg->country_code = CTRY_UNITED_STATES;
 521        }
 522
 523        if (reg->country_code == CTRY_DEFAULT) {
 524                country = NULL;
 525        } else {
 526                printk(KERN_DEBUG "ath: doing EEPROM country->regdmn "
 527                       "map search\n");
 528                country = ath_regd_find_country(reg->country_code);
 529                if (country == NULL) {
 530                        printk(KERN_DEBUG
 531                                "ath: no valid country maps found for "
 532                                "country code: 0x%0x\n",
 533                                reg->country_code);
 534                        return -EINVAL;
 535                } else {
 536                        regdmn = country->regDmnEnum;
 537                        printk(KERN_DEBUG "ath: country maps to "
 538                               "regdmn code: 0x%0x\n",
 539                               regdmn);
 540                }
 541        }
 542
 543        reg->regpair = ath_get_regpair(regdmn);
 544
 545        if (!reg->regpair) {
 546                printk(KERN_DEBUG "ath: "
 547                        "No regulatory domain pair found, cannot continue\n");
 548                return -EINVAL;
 549        }
 550
 551        if (!country)
 552                country = ath_regd_find_country_by_rd(regdmn);
 553
 554        if (country) {
 555                reg->alpha2[0] = country->isoName[0];
 556                reg->alpha2[1] = country->isoName[1];
 557        } else {
 558                reg->alpha2[0] = '0';
 559                reg->alpha2[1] = '0';
 560        }
 561
 562        printk(KERN_DEBUG "ath: Country alpha2 being used: %c%c\n",
 563                reg->alpha2[0], reg->alpha2[1]);
 564        printk(KERN_DEBUG "ath: Regpair used: 0x%0x\n",
 565                reg->regpair->regDmnEnum);
 566
 567        ath_regd_init_wiphy(reg, wiphy, reg_notifier);
 568        return 0;
 569}
 570EXPORT_SYMBOL(ath_regd_init);
 571
 572u32 ath_regd_get_band_ctl(struct ath_regulatory *reg,
 573                          enum ieee80211_band band)
 574{
 575        if (!reg->regpair ||
 576            (reg->country_code == CTRY_DEFAULT &&
 577             is_wwr_sku(ath_regd_get_eepromRD(reg)))) {
 578                return SD_NO_CTL;
 579        }
 580
 581        switch (band) {
 582        case IEEE80211_BAND_2GHZ:
 583                return reg->regpair->reg_2ghz_ctl;
 584        case IEEE80211_BAND_5GHZ:
 585                return reg->regpair->reg_5ghz_ctl;
 586        default:
 587                return NO_CTL;
 588        }
 589}
 590EXPORT_SYMBOL(ath_regd_get_band_ctl);
 591