linux/drivers/staging/rtlwifi/regd.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/******************************************************************************
   3 *
   4 * Copyright(c) 2009-2012  Realtek Corporation.
   5 *
   6 * Contact Information:
   7 * wlanfae <wlanfae@realtek.com>
   8 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
   9 * Hsinchu 300, Taiwan.
  10 *
  11 * Larry Finger <Larry.Finger@lwfinger.net>
  12 *
  13 *****************************************************************************/
  14
  15#include "wifi.h"
  16#include "regd.h"
  17
  18static struct country_code_to_enum_rd allcountries[] = {
  19        {COUNTRY_CODE_FCC, "US"},
  20        {COUNTRY_CODE_IC, "US"},
  21        {COUNTRY_CODE_ETSI, "EC"},
  22        {COUNTRY_CODE_SPAIN, "EC"},
  23        {COUNTRY_CODE_FRANCE, "EC"},
  24        {COUNTRY_CODE_MKK, "JP"},
  25        {COUNTRY_CODE_MKK1, "JP"},
  26        {COUNTRY_CODE_ISRAEL, "EC"},
  27        {COUNTRY_CODE_TELEC, "JP"},
  28        {COUNTRY_CODE_MIC, "JP"},
  29        {COUNTRY_CODE_GLOBAL_DOMAIN, "JP"},
  30        {COUNTRY_CODE_WORLD_WIDE_13, "EC"},
  31        {COUNTRY_CODE_TELEC_NETGEAR, "EC"},
  32        {COUNTRY_CODE_WORLD_WIDE_13_5G_ALL, "US"},
  33};
  34
  35/*Only these channels all allow active
  36 *scan on all world regulatory domains
  37 */
  38#define RTL819x_2GHZ_CH01_11    \
  39        REG_RULE(2412 - 10, 2462 + 10, 40, 0, 20, 0)
  40
  41/*We enable active scan on these a case
  42 *by case basis by regulatory domain
  43 */
  44#define RTL819x_2GHZ_CH12_13    \
  45        REG_RULE(2467 - 10, 2472 + 10, 40, 0, 20,\
  46        NL80211_RRF_PASSIVE_SCAN)
  47
  48#define RTL819x_2GHZ_CH14       \
  49        REG_RULE(2484 - 10, 2484 + 10, 40, 0, 20, \
  50        NL80211_RRF_PASSIVE_SCAN | \
  51        NL80211_RRF_NO_OFDM)
  52
  53/* 5G chan 36 - chan 64*/
  54#define RTL819x_5GHZ_5150_5350  \
  55        REG_RULE(5150 - 10, 5350 + 10, 80, 0, 30, 0)
  56/* 5G chan 100 - chan 165*/
  57#define RTL819x_5GHZ_5470_5850  \
  58        REG_RULE(5470 - 10, 5850 + 10, 80, 0, 30, 0)
  59/* 5G chan 149 - chan 165*/
  60#define RTL819x_5GHZ_5725_5850  \
  61        REG_RULE(5725 - 10, 5850 + 10, 80, 0, 30, 0)
  62
  63#define RTL819x_5GHZ_ALL        \
  64        (RTL819x_5GHZ_5150_5350, RTL819x_5GHZ_5470_5850)
  65
  66static const struct ieee80211_regdomain rtl_regdom_11 = {
  67        .n_reg_rules = 1,
  68        .alpha2 = "99",
  69        .reg_rules = {
  70                RTL819x_2GHZ_CH01_11,
  71        }
  72};
  73
  74static const struct ieee80211_regdomain rtl_regdom_12_13 = {
  75        .n_reg_rules = 2,
  76        .alpha2 = "99",
  77        .reg_rules = {
  78                RTL819x_2GHZ_CH01_11,
  79                RTL819x_2GHZ_CH12_13,
  80        }
  81};
  82
  83static const struct ieee80211_regdomain rtl_regdom_no_midband = {
  84        .n_reg_rules = 3,
  85        .alpha2 = "99",
  86        .reg_rules = {
  87                RTL819x_2GHZ_CH01_11,
  88                RTL819x_5GHZ_5150_5350,
  89                RTL819x_5GHZ_5725_5850,
  90        }
  91};
  92
  93static const struct ieee80211_regdomain rtl_regdom_60_64 = {
  94        .n_reg_rules = 3,
  95        .alpha2 = "99",
  96        .reg_rules = {
  97                RTL819x_2GHZ_CH01_11,
  98                RTL819x_2GHZ_CH12_13,
  99                RTL819x_5GHZ_5725_5850,
 100        }
 101};
 102
 103static const struct ieee80211_regdomain rtl_regdom_14_60_64 = {
 104        .n_reg_rules = 4,
 105        .alpha2 = "99",
 106        .reg_rules = {
 107                RTL819x_2GHZ_CH01_11,
 108                RTL819x_2GHZ_CH12_13,
 109                RTL819x_2GHZ_CH14,
 110                RTL819x_5GHZ_5725_5850,
 111        }
 112};
 113
 114static const struct ieee80211_regdomain rtl_regdom_12_13_5g_all = {
 115        .n_reg_rules = 4,
 116        .alpha2 = "99",
 117        .reg_rules = {
 118                RTL819x_2GHZ_CH01_11,
 119                RTL819x_2GHZ_CH12_13,
 120                RTL819x_5GHZ_5150_5350,
 121                RTL819x_5GHZ_5470_5850,
 122        }
 123};
 124
 125static const struct ieee80211_regdomain rtl_regdom_14 = {
 126        .n_reg_rules = 3,
 127        .alpha2 = "99",
 128        .reg_rules = {
 129                RTL819x_2GHZ_CH01_11,
 130                RTL819x_2GHZ_CH12_13,
 131                RTL819x_2GHZ_CH14,
 132        }
 133};
 134
 135static bool _rtl_is_radar_freq(u16 center_freq)
 136{
 137        return center_freq >= 5260 && center_freq <= 5700;
 138}
 139
 140static void _rtl_reg_apply_beaconing_flags(struct wiphy *wiphy,
 141                                           enum nl80211_reg_initiator initiator)
 142{
 143        enum nl80211_band band;
 144        struct ieee80211_supported_band *sband;
 145        const struct ieee80211_reg_rule *reg_rule;
 146        struct ieee80211_channel *ch;
 147        unsigned int i;
 148
 149        for (band = 0; band < NUM_NL80211_BANDS; band++) {
 150                if (!wiphy->bands[band])
 151                        continue;
 152
 153                sband = wiphy->bands[band];
 154
 155                for (i = 0; i < sband->n_channels; i++) {
 156                        ch = &sband->channels[i];
 157                        if (_rtl_is_radar_freq(ch->center_freq) ||
 158                            (ch->flags & IEEE80211_CHAN_RADAR))
 159                                continue;
 160                        if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
 161                                reg_rule = freq_reg_info(wiphy,
 162                                                         ch->center_freq);
 163                                if (IS_ERR(reg_rule))
 164                                        continue;
 165                                /*
 166                                 *If 11d had a rule for this channel ensure
 167                                 *we enable adhoc/beaconing if it allows us to
 168                                 *use it. Note that we would have disabled it
 169                                 *by applying our static world regdomain by
 170                                 *default during init, prior to calling our
 171                                 *regulatory_hint().
 172                                 */
 173
 174                                if (!(reg_rule->flags & NL80211_RRF_NO_IBSS))
 175                                        ch->flags &= ~IEEE80211_CHAN_NO_IBSS;
 176                                if (!(reg_rule->flags &
 177                                      NL80211_RRF_PASSIVE_SCAN))
 178                                        ch->flags &=
 179                                            ~IEEE80211_CHAN_PASSIVE_SCAN;
 180                        } else {
 181                                if (ch->beacon_found)
 182                                        ch->flags &= ~(IEEE80211_CHAN_NO_IBSS |
 183                                                   IEEE80211_CHAN_PASSIVE_SCAN);
 184                        }
 185                }
 186        }
 187}
 188
 189/* Allows active scan scan on Ch 12 and 13 */
 190static void _rtl_reg_apply_active_scan_flags(struct wiphy *wiphy,
 191                                             enum nl80211_reg_initiator
 192                                             initiator)
 193{
 194        struct ieee80211_supported_band *sband;
 195        struct ieee80211_channel *ch;
 196        const struct ieee80211_reg_rule *reg_rule;
 197
 198        if (!wiphy->bands[NL80211_BAND_2GHZ])
 199                return;
 200        sband = wiphy->bands[NL80211_BAND_2GHZ];
 201
 202        /*
 203         *If no country IE has been received always enable active scan
 204         *on these channels. This is only done for specific regulatory SKUs
 205         */
 206        if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
 207                ch = &sband->channels[11];      /* CH 12 */
 208                if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
 209                        ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
 210                ch = &sband->channels[12];      /* CH 13 */
 211                if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
 212                        ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
 213                return;
 214        }
 215
 216        /*If a country IE has been received check its rule for this
 217         *channel first before enabling active scan. The passive scan
 218         *would have been enforced by the initial processing of our
 219         *custom regulatory domain.
 220         */
 221
 222        ch = &sband->channels[11];      /* CH 12 */
 223        reg_rule = freq_reg_info(wiphy, ch->center_freq);
 224        if (!IS_ERR(reg_rule)) {
 225                if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
 226                        if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
 227                                ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
 228        }
 229
 230        ch = &sband->channels[12];      /* CH 13 */
 231        reg_rule = freq_reg_info(wiphy, ch->center_freq);
 232        if (!IS_ERR(reg_rule)) {
 233                if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
 234                        if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
 235                                ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
 236        }
 237}
 238
 239/*
 240 *Always apply Radar/DFS rules on
 241 *freq range 5260 MHz - 5700 MHz
 242 */
 243static void _rtl_reg_apply_radar_flags(struct wiphy *wiphy)
 244{
 245        struct ieee80211_supported_band *sband;
 246        struct ieee80211_channel *ch;
 247        unsigned int i;
 248
 249        if (!wiphy->bands[NL80211_BAND_5GHZ])
 250                return;
 251
 252        sband = wiphy->bands[NL80211_BAND_5GHZ];
 253
 254        for (i = 0; i < sband->n_channels; i++) {
 255                ch = &sband->channels[i];
 256                if (!_rtl_is_radar_freq(ch->center_freq))
 257                        continue;
 258
 259                /*
 260                 *We always enable radar detection/DFS on this
 261                 *frequency range. Additionally we also apply on
 262                 *this frequency range:
 263                 *- If STA mode does not yet have DFS supports disable
 264                 * active scanning
 265                 *- If adhoc mode does not support DFS yet then disable
 266                 * adhoc in the frequency.
 267                 *- If AP mode does not yet support radar detection/DFS
 268                 *do not allow AP mode
 269                 */
 270                if (!(ch->flags & IEEE80211_CHAN_DISABLED))
 271                        ch->flags |= IEEE80211_CHAN_RADAR |
 272                            IEEE80211_CHAN_NO_IBSS |
 273                            IEEE80211_CHAN_PASSIVE_SCAN;
 274        }
 275}
 276
 277static void _rtl_reg_apply_world_flags(struct wiphy *wiphy,
 278                                       enum nl80211_reg_initiator initiator,
 279                                       struct rtl_regulatory *reg)
 280{
 281        _rtl_reg_apply_beaconing_flags(wiphy, initiator);
 282        _rtl_reg_apply_active_scan_flags(wiphy, initiator);
 283}
 284
 285static void _rtl_dump_channel_map(struct wiphy *wiphy)
 286{
 287        enum nl80211_band band;
 288        struct ieee80211_supported_band *sband;
 289        struct ieee80211_channel *ch;
 290        unsigned int i;
 291
 292        for (band = 0; band < NUM_NL80211_BANDS; band++) {
 293                if (!wiphy->bands[band])
 294                        continue;
 295                sband = wiphy->bands[band];
 296                for (i = 0; i < sband->n_channels; i++)
 297                        ch = &sband->channels[i];
 298        }
 299}
 300
 301static int _rtl_reg_notifier_apply(struct wiphy *wiphy,
 302                                   struct regulatory_request *request,
 303                                   struct rtl_regulatory *reg)
 304{
 305        /* We always apply this */
 306        _rtl_reg_apply_radar_flags(wiphy);
 307
 308        switch (request->initiator) {
 309        case NL80211_REGDOM_SET_BY_DRIVER:
 310        case NL80211_REGDOM_SET_BY_CORE:
 311        case NL80211_REGDOM_SET_BY_USER:
 312                break;
 313        case NL80211_REGDOM_SET_BY_COUNTRY_IE:
 314                _rtl_reg_apply_world_flags(wiphy, request->initiator, reg);
 315                break;
 316        }
 317
 318        _rtl_dump_channel_map(wiphy);
 319
 320        return 0;
 321}
 322
 323static const struct ieee80211_regdomain *_rtl_regdomain_select(
 324                                                struct rtl_regulatory *reg)
 325{
 326        switch (reg->country_code) {
 327        case COUNTRY_CODE_FCC:
 328                return &rtl_regdom_no_midband;
 329        case COUNTRY_CODE_IC:
 330                return &rtl_regdom_11;
 331        case COUNTRY_CODE_TELEC_NETGEAR:
 332                return &rtl_regdom_60_64;
 333        case COUNTRY_CODE_ETSI:
 334        case COUNTRY_CODE_SPAIN:
 335        case COUNTRY_CODE_FRANCE:
 336        case COUNTRY_CODE_ISRAEL:
 337                return &rtl_regdom_12_13;
 338        case COUNTRY_CODE_MKK:
 339        case COUNTRY_CODE_MKK1:
 340        case COUNTRY_CODE_TELEC:
 341        case COUNTRY_CODE_MIC:
 342                return &rtl_regdom_14_60_64;
 343        case COUNTRY_CODE_GLOBAL_DOMAIN:
 344                return &rtl_regdom_14;
 345        case COUNTRY_CODE_WORLD_WIDE_13:
 346        case COUNTRY_CODE_WORLD_WIDE_13_5G_ALL:
 347                return &rtl_regdom_12_13_5g_all;
 348        default:
 349                return &rtl_regdom_no_midband;
 350        }
 351}
 352
 353static int _rtl_regd_init_wiphy(struct rtl_regulatory *reg,
 354                                struct wiphy *wiphy,
 355                                void (*reg_notifier)(struct wiphy *wiphy,
 356                                                     struct regulatory_request *
 357                                                     request))
 358{
 359        const struct ieee80211_regdomain *regd;
 360
 361        wiphy->reg_notifier = reg_notifier;
 362
 363        wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
 364        wiphy->regulatory_flags &= ~REGULATORY_STRICT_REG;
 365        wiphy->regulatory_flags &= ~REGULATORY_DISABLE_BEACON_HINTS;
 366        regd = _rtl_regdomain_select(reg);
 367        wiphy_apply_custom_regulatory(wiphy, regd);
 368        _rtl_reg_apply_radar_flags(wiphy);
 369        _rtl_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg);
 370        return 0;
 371}
 372
 373static struct country_code_to_enum_rd *_rtl_regd_find_country(u16 countrycode)
 374{
 375        int i;
 376
 377        for (i = 0; i < ARRAY_SIZE(allcountries); i++) {
 378                if (allcountries[i].countrycode == countrycode)
 379                        return &allcountries[i];
 380        }
 381        return NULL;
 382}
 383
 384static u8 channel_plan_to_country_code(u8 channelplan)
 385{
 386        switch (channelplan) {
 387        case 0x20:
 388        case 0x21:
 389                return COUNTRY_CODE_WORLD_WIDE_13;
 390        case 0x22:
 391                return COUNTRY_CODE_IC;
 392        case 0x25:
 393                return COUNTRY_CODE_ETSI;
 394        case 0x32:
 395                return COUNTRY_CODE_TELEC_NETGEAR;
 396        case 0x41:
 397                return COUNTRY_CODE_GLOBAL_DOMAIN;
 398        case 0x7f:
 399                return COUNTRY_CODE_WORLD_WIDE_13_5G_ALL;
 400        default:
 401                return COUNTRY_CODE_MAX; /*Error*/
 402        }
 403}
 404
 405int rtl_regd_init(struct ieee80211_hw *hw,
 406                  void (*reg_notifier)(struct wiphy *wiphy,
 407                                       struct regulatory_request *request))
 408{
 409        struct rtl_priv *rtlpriv = rtl_priv(hw);
 410        struct wiphy *wiphy = hw->wiphy;
 411        struct country_code_to_enum_rd *country = NULL;
 412
 413        if (!wiphy || !&rtlpriv->regd)
 414                return -EINVAL;
 415
 416        /* init country_code from efuse channel plan */
 417        rtlpriv->regd.country_code =
 418                channel_plan_to_country_code(rtlpriv->efuse.channel_plan);
 419
 420        RT_TRACE(rtlpriv, COMP_REGD, DBG_DMESG,
 421                 "rtl: EEPROM regdomain: 0x%0x country code: %d\n",
 422                 rtlpriv->efuse.channel_plan, rtlpriv->regd.country_code);
 423
 424        if (rtlpriv->regd.country_code >= COUNTRY_CODE_MAX) {
 425                RT_TRACE(rtlpriv, COMP_REGD, DBG_DMESG,
 426                         "rtl: EEPROM indicates invalid country code, world wide 13 should be used\n");
 427
 428                rtlpriv->regd.country_code = COUNTRY_CODE_WORLD_WIDE_13;
 429        }
 430
 431        country = _rtl_regd_find_country(rtlpriv->regd.country_code);
 432
 433        if (country) {
 434                rtlpriv->regd.alpha2[0] = country->iso_name[0];
 435                rtlpriv->regd.alpha2[1] = country->iso_name[1];
 436        } else {
 437                rtlpriv->regd.alpha2[0] = '0';
 438                rtlpriv->regd.alpha2[1] = '0';
 439        }
 440
 441        RT_TRACE(rtlpriv, COMP_REGD, DBG_TRACE,
 442                 "rtl: Country alpha2 being used: %c%c\n",
 443                  rtlpriv->regd.alpha2[0], rtlpriv->regd.alpha2[1]);
 444
 445        _rtl_regd_init_wiphy(&rtlpriv->regd, wiphy, reg_notifier);
 446
 447        return 0;
 448}
 449
 450void rtl_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
 451{
 452        struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
 453        struct rtl_priv *rtlpriv = rtl_priv(hw);
 454
 455        RT_TRACE(rtlpriv, COMP_REGD, DBG_LOUD, "\n");
 456
 457        _rtl_reg_notifier_apply(wiphy, request, &rtlpriv->regd);
 458}
 459