root/drivers/net/wireless/realtek/rtlwifi/regd.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _rtl_is_radar_freq
  2. _rtl_reg_apply_beaconing_flags
  3. _rtl_reg_apply_active_scan_flags
  4. _rtl_reg_apply_radar_flags
  5. _rtl_reg_apply_world_flags
  6. _rtl_reg_notifier_apply
  7. _rtl_regdomain_select
  8. _rtl_regd_init_wiphy
  9. _rtl_regd_find_country
  10. channel_plan_to_country_code
  11. rtl_regd_init
  12. rtl_reg_notifier

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

/* [<][>][^][v][top][bottom][index][help] */