Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright(c) 2009-2012  Realtek Corporation.*/
0003 
0004 #include "wifi.h"
0005 #include "regd.h"
0006 
0007 static struct country_code_to_enum_rd all_countries[] = {
0008     {COUNTRY_CODE_FCC, "US"},
0009     {COUNTRY_CODE_IC, "US"},
0010     {COUNTRY_CODE_ETSI, "EC"},
0011     {COUNTRY_CODE_SPAIN, "EC"},
0012     {COUNTRY_CODE_FRANCE, "EC"},
0013     {COUNTRY_CODE_MKK, "JP"},
0014     {COUNTRY_CODE_MKK1, "JP"},
0015     {COUNTRY_CODE_ISRAEL, "EC"},
0016     {COUNTRY_CODE_TELEC, "JP"},
0017     {COUNTRY_CODE_MIC, "JP"},
0018     {COUNTRY_CODE_GLOBAL_DOMAIN, "JP"},
0019     {COUNTRY_CODE_WORLD_WIDE_13, "EC"},
0020     {COUNTRY_CODE_TELEC_NETGEAR, "EC"},
0021     {COUNTRY_CODE_WORLD_WIDE_13_5G_ALL, "US"},
0022 };
0023 
0024 /*
0025  *Only these channels all allow active
0026  *scan on all world regulatory domains
0027  */
0028 #define RTL819x_2GHZ_CH01_11    \
0029     REG_RULE(2412-10, 2462+10, 40, 0, 20, 0)
0030 
0031 /*
0032  *We enable active scan on these a case
0033  *by case basis by regulatory domain
0034  */
0035 #define RTL819x_2GHZ_CH12_13    \
0036     REG_RULE(2467-10, 2472+10, 40, 0, 20,\
0037     NL80211_RRF_PASSIVE_SCAN)
0038 
0039 #define RTL819x_2GHZ_CH14   \
0040     REG_RULE(2484-10, 2484+10, 40, 0, 20, \
0041     NL80211_RRF_PASSIVE_SCAN | \
0042     NL80211_RRF_NO_OFDM)
0043 
0044 /* 5G chan 36 - chan 64*/
0045 #define RTL819x_5GHZ_5150_5350  \
0046     REG_RULE(5150-10, 5350+10, 80, 0, 30, 0)
0047 /* 5G chan 100 - chan 165*/
0048 #define RTL819x_5GHZ_5470_5850  \
0049     REG_RULE(5470-10, 5850+10, 80, 0, 30, 0)
0050 /* 5G chan 149 - chan 165*/
0051 #define RTL819x_5GHZ_5725_5850  \
0052     REG_RULE(5725-10, 5850+10, 80, 0, 30, 0)
0053 
0054 #define RTL819x_5GHZ_ALL    \
0055     (RTL819x_5GHZ_5150_5350, RTL819x_5GHZ_5470_5850)
0056 
0057 static const struct ieee80211_regdomain rtl_regdom_11 = {
0058     .n_reg_rules = 1,
0059     .alpha2 = "99",
0060     .reg_rules = {
0061               RTL819x_2GHZ_CH01_11,
0062               }
0063 };
0064 
0065 static const struct ieee80211_regdomain rtl_regdom_12_13 = {
0066     .n_reg_rules = 2,
0067     .alpha2 = "99",
0068     .reg_rules = {
0069               RTL819x_2GHZ_CH01_11,
0070               RTL819x_2GHZ_CH12_13,
0071               }
0072 };
0073 
0074 static const struct ieee80211_regdomain rtl_regdom_no_midband = {
0075     .n_reg_rules = 3,
0076     .alpha2 = "99",
0077     .reg_rules = {
0078               RTL819x_2GHZ_CH01_11,
0079               RTL819x_5GHZ_5150_5350,
0080               RTL819x_5GHZ_5725_5850,
0081               }
0082 };
0083 
0084 static const struct ieee80211_regdomain rtl_regdom_60_64 = {
0085     .n_reg_rules = 3,
0086     .alpha2 = "99",
0087     .reg_rules = {
0088               RTL819x_2GHZ_CH01_11,
0089               RTL819x_2GHZ_CH12_13,
0090               RTL819x_5GHZ_5725_5850,
0091               }
0092 };
0093 
0094 static const struct ieee80211_regdomain rtl_regdom_14_60_64 = {
0095     .n_reg_rules = 4,
0096     .alpha2 = "99",
0097     .reg_rules = {
0098               RTL819x_2GHZ_CH01_11,
0099               RTL819x_2GHZ_CH12_13,
0100               RTL819x_2GHZ_CH14,
0101               RTL819x_5GHZ_5725_5850,
0102               }
0103 };
0104 
0105 static const struct ieee80211_regdomain rtl_regdom_12_13_5g_all = {
0106     .n_reg_rules = 4,
0107     .alpha2 = "99",
0108     .reg_rules = {
0109             RTL819x_2GHZ_CH01_11,
0110             RTL819x_2GHZ_CH12_13,
0111             RTL819x_5GHZ_5150_5350,
0112             RTL819x_5GHZ_5470_5850,
0113         }
0114 };
0115 
0116 static const struct ieee80211_regdomain rtl_regdom_14 = {
0117     .n_reg_rules = 3,
0118     .alpha2 = "99",
0119     .reg_rules = {
0120               RTL819x_2GHZ_CH01_11,
0121               RTL819x_2GHZ_CH12_13,
0122               RTL819x_2GHZ_CH14,
0123               }
0124 };
0125 
0126 static bool _rtl_is_radar_freq(u16 center_freq)
0127 {
0128     return center_freq >= 5260 && center_freq <= 5700;
0129 }
0130 
0131 static void _rtl_reg_apply_beaconing_flags(struct wiphy *wiphy,
0132                        enum nl80211_reg_initiator initiator)
0133 {
0134     enum nl80211_band band;
0135     struct ieee80211_supported_band *sband;
0136     const struct ieee80211_reg_rule *reg_rule;
0137     struct ieee80211_channel *ch;
0138     unsigned int i;
0139 
0140     for (band = 0; band < NUM_NL80211_BANDS; band++) {
0141 
0142         if (!wiphy->bands[band])
0143             continue;
0144 
0145         sband = wiphy->bands[band];
0146 
0147         for (i = 0; i < sband->n_channels; i++) {
0148             ch = &sband->channels[i];
0149             if (_rtl_is_radar_freq(ch->center_freq) ||
0150                 (ch->flags & IEEE80211_CHAN_RADAR))
0151                 continue;
0152             if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
0153                 reg_rule = freq_reg_info(wiphy,
0154                              ch->center_freq);
0155                 if (IS_ERR(reg_rule))
0156                     continue;
0157                 /*
0158                  *If 11d had a rule for this channel ensure
0159                  *we enable adhoc/beaconing if it allows us to
0160                  *use it. Note that we would have disabled it
0161                  *by applying our static world regdomain by
0162                  *default during init, prior to calling our
0163                  *regulatory_hint().
0164                  */
0165 
0166                 if (!(reg_rule->flags & NL80211_RRF_NO_IBSS))
0167                     ch->flags &= ~IEEE80211_CHAN_NO_IBSS;
0168                 if (!(reg_rule->flags &
0169                       NL80211_RRF_PASSIVE_SCAN))
0170                     ch->flags &=
0171                         ~IEEE80211_CHAN_PASSIVE_SCAN;
0172             } else {
0173                 if (ch->beacon_found)
0174                     ch->flags &= ~(IEEE80211_CHAN_NO_IBSS |
0175                            IEEE80211_CHAN_PASSIVE_SCAN);
0176             }
0177         }
0178     }
0179 }
0180 
0181 /* Allows active scan on Ch 12 and 13 */
0182 static void _rtl_reg_apply_active_scan_flags(struct wiphy *wiphy,
0183                          enum nl80211_reg_initiator
0184                          initiator)
0185 {
0186     struct ieee80211_supported_band *sband;
0187     struct ieee80211_channel *ch;
0188     const struct ieee80211_reg_rule *reg_rule;
0189 
0190     if (!wiphy->bands[NL80211_BAND_2GHZ])
0191         return;
0192     sband = wiphy->bands[NL80211_BAND_2GHZ];
0193 
0194     /*
0195      *If no country IE has been received always enable active scan
0196      *on these channels. This is only done for specific regulatory SKUs
0197      */
0198     if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
0199         ch = &sband->channels[11];  /* CH 12 */
0200         if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
0201             ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
0202         ch = &sband->channels[12];  /* CH 13 */
0203         if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
0204             ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
0205         return;
0206     }
0207 
0208     /*
0209      *If a country IE has been recieved check its rule for this
0210      *channel first before enabling active scan. The passive scan
0211      *would have been enforced by the initial processing of our
0212      *custom regulatory domain.
0213      */
0214 
0215     ch = &sband->channels[11];  /* CH 12 */
0216     reg_rule = freq_reg_info(wiphy, ch->center_freq);
0217     if (!IS_ERR(reg_rule)) {
0218         if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
0219             if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
0220                 ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
0221     }
0222 
0223     ch = &sband->channels[12];  /* CH 13 */
0224     reg_rule = freq_reg_info(wiphy, ch->center_freq);
0225     if (!IS_ERR(reg_rule)) {
0226         if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
0227             if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
0228                 ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
0229     }
0230 }
0231 
0232 /*
0233  *Always apply Radar/DFS rules on
0234  *freq range 5260 MHz - 5700 MHz
0235  */
0236 static void _rtl_reg_apply_radar_flags(struct wiphy *wiphy)
0237 {
0238     struct ieee80211_supported_band *sband;
0239     struct ieee80211_channel *ch;
0240     unsigned int i;
0241 
0242     if (!wiphy->bands[NL80211_BAND_5GHZ])
0243         return;
0244 
0245     sband = wiphy->bands[NL80211_BAND_5GHZ];
0246 
0247     for (i = 0; i < sband->n_channels; i++) {
0248         ch = &sband->channels[i];
0249         if (!_rtl_is_radar_freq(ch->center_freq))
0250             continue;
0251 
0252         /*
0253          *We always enable radar detection/DFS on this
0254          *frequency range. Additionally we also apply on
0255          *this frequency range:
0256          *- If STA mode does not yet have DFS supports disable
0257          * active scanning
0258          *- If adhoc mode does not support DFS yet then disable
0259          * adhoc in the frequency.
0260          *- If AP mode does not yet support radar detection/DFS
0261          *do not allow AP mode
0262          */
0263         if (!(ch->flags & IEEE80211_CHAN_DISABLED))
0264             ch->flags |= IEEE80211_CHAN_RADAR |
0265                 IEEE80211_CHAN_NO_IBSS |
0266                 IEEE80211_CHAN_PASSIVE_SCAN;
0267     }
0268 }
0269 
0270 static void _rtl_reg_apply_world_flags(struct wiphy *wiphy,
0271                        enum nl80211_reg_initiator initiator,
0272                        struct rtl_regulatory *reg)
0273 {
0274     _rtl_reg_apply_beaconing_flags(wiphy, initiator);
0275     _rtl_reg_apply_active_scan_flags(wiphy, initiator);
0276     return;
0277 }
0278 
0279 static int _rtl_reg_notifier_apply(struct wiphy *wiphy,
0280                    struct regulatory_request *request,
0281                    struct rtl_regulatory *reg)
0282 {
0283     /* We always apply this */
0284     _rtl_reg_apply_radar_flags(wiphy);
0285 
0286     switch (request->initiator) {
0287     case NL80211_REGDOM_SET_BY_DRIVER:
0288     case NL80211_REGDOM_SET_BY_CORE:
0289     case NL80211_REGDOM_SET_BY_USER:
0290         break;
0291     case NL80211_REGDOM_SET_BY_COUNTRY_IE:
0292         _rtl_reg_apply_world_flags(wiphy, request->initiator, reg);
0293         break;
0294     }
0295 
0296     return 0;
0297 }
0298 
0299 static const struct ieee80211_regdomain *_rtl_regdomain_select(
0300                         struct rtl_regulatory *reg)
0301 {
0302     switch (reg->country_code) {
0303     case COUNTRY_CODE_FCC:
0304         return &rtl_regdom_no_midband;
0305     case COUNTRY_CODE_IC:
0306         return &rtl_regdom_11;
0307     case COUNTRY_CODE_TELEC_NETGEAR:
0308         return &rtl_regdom_60_64;
0309     case COUNTRY_CODE_ETSI:
0310     case COUNTRY_CODE_SPAIN:
0311     case COUNTRY_CODE_FRANCE:
0312     case COUNTRY_CODE_ISRAEL:
0313         return &rtl_regdom_12_13;
0314     case COUNTRY_CODE_MKK:
0315     case COUNTRY_CODE_MKK1:
0316     case COUNTRY_CODE_TELEC:
0317     case COUNTRY_CODE_MIC:
0318         return &rtl_regdom_14_60_64;
0319     case COUNTRY_CODE_GLOBAL_DOMAIN:
0320         return &rtl_regdom_14;
0321     case COUNTRY_CODE_WORLD_WIDE_13:
0322     case COUNTRY_CODE_WORLD_WIDE_13_5G_ALL:
0323         return &rtl_regdom_12_13_5g_all;
0324     default:
0325         return &rtl_regdom_no_midband;
0326     }
0327 }
0328 
0329 static int _rtl_regd_init_wiphy(struct rtl_regulatory *reg,
0330                 struct wiphy *wiphy,
0331                 void (*reg_notifier)(struct wiphy *wiphy,
0332                              struct regulatory_request *
0333                              request))
0334 {
0335     const struct ieee80211_regdomain *regd;
0336 
0337     wiphy->reg_notifier = reg_notifier;
0338 
0339     wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
0340     wiphy->regulatory_flags &= ~REGULATORY_STRICT_REG;
0341     wiphy->regulatory_flags &= ~REGULATORY_DISABLE_BEACON_HINTS;
0342     regd = _rtl_regdomain_select(reg);
0343     wiphy_apply_custom_regulatory(wiphy, regd);
0344     _rtl_reg_apply_radar_flags(wiphy);
0345     _rtl_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg);
0346     return 0;
0347 }
0348 
0349 static struct country_code_to_enum_rd *_rtl_regd_find_country(u16 countrycode)
0350 {
0351     int i;
0352 
0353     for (i = 0; i < ARRAY_SIZE(all_countries); i++) {
0354         if (all_countries[i].countrycode == countrycode)
0355             return &all_countries[i];
0356     }
0357     return NULL;
0358 }
0359 
0360 static u8 channel_plan_to_country_code(u8 channelplan)
0361 {
0362     switch (channelplan) {
0363     case 0x20:
0364     case 0x21:
0365         return COUNTRY_CODE_WORLD_WIDE_13;
0366     case 0x22:
0367         return COUNTRY_CODE_IC;
0368     case 0x25:
0369         return COUNTRY_CODE_ETSI;
0370     case 0x32:
0371         return COUNTRY_CODE_TELEC_NETGEAR;
0372     case 0x41:
0373         return COUNTRY_CODE_GLOBAL_DOMAIN;
0374     case 0x7f:
0375         return COUNTRY_CODE_WORLD_WIDE_13_5G_ALL;
0376     default:
0377         return COUNTRY_CODE_MAX; /*Error*/
0378     }
0379 }
0380 
0381 int rtl_regd_init(struct ieee80211_hw *hw,
0382           void (*reg_notifier)(struct wiphy *wiphy,
0383                        struct regulatory_request *request))
0384 {
0385     struct rtl_priv *rtlpriv = rtl_priv(hw);
0386     struct wiphy *wiphy = hw->wiphy;
0387     struct country_code_to_enum_rd *country = NULL;
0388 
0389     if (!wiphy)
0390         return -EINVAL;
0391 
0392     /* init country_code from efuse channel plan */
0393     rtlpriv->regd.country_code =
0394         channel_plan_to_country_code(rtlpriv->efuse.channel_plan);
0395 
0396     rtl_dbg(rtlpriv, COMP_REGD, DBG_DMESG,
0397         "rtl: EEPROM regdomain: 0x%0x country code: %d\n",
0398         rtlpriv->efuse.channel_plan, rtlpriv->regd.country_code);
0399 
0400     if (rtlpriv->regd.country_code >= COUNTRY_CODE_MAX) {
0401         rtl_dbg(rtlpriv, COMP_REGD, DBG_DMESG,
0402             "rtl: EEPROM indicates invalid country code, world wide 13 should be used\n");
0403 
0404         rtlpriv->regd.country_code = COUNTRY_CODE_WORLD_WIDE_13;
0405     }
0406 
0407     country = _rtl_regd_find_country(rtlpriv->regd.country_code);
0408 
0409     if (country) {
0410         rtlpriv->regd.alpha2[0] = country->iso_name[0];
0411         rtlpriv->regd.alpha2[1] = country->iso_name[1];
0412     } else {
0413         rtlpriv->regd.alpha2[0] = '0';
0414         rtlpriv->regd.alpha2[1] = '0';
0415     }
0416 
0417     rtl_dbg(rtlpriv, COMP_REGD, DBG_TRACE,
0418         "rtl: Country alpha2 being used: %c%c\n",
0419         rtlpriv->regd.alpha2[0], rtlpriv->regd.alpha2[1]);
0420 
0421     _rtl_regd_init_wiphy(&rtlpriv->regd, wiphy, reg_notifier);
0422 
0423     return 0;
0424 }
0425 
0426 void rtl_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
0427 {
0428     struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
0429     struct rtl_priv *rtlpriv = rtl_priv(hw);
0430 
0431     rtl_dbg(rtlpriv, COMP_REGD, DBG_LOUD, "\n");
0432 
0433     _rtl_reg_notifier_apply(wiphy, request, &rtlpriv->regd);
0434 }