0001
0002
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
0026
0027
0028 #define RTL819x_2GHZ_CH01_11 \
0029 REG_RULE(2412-10, 2462+10, 40, 0, 20, 0)
0030
0031
0032
0033
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
0045 #define RTL819x_5GHZ_5150_5350 \
0046 REG_RULE(5150-10, 5350+10, 80, 0, 30, 0)
0047
0048 #define RTL819x_5GHZ_5470_5850 \
0049 REG_RULE(5470-10, 5850+10, 80, 0, 30, 0)
0050
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
0159
0160
0161
0162
0163
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
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
0196
0197
0198 if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
0199 ch = &sband->channels[11];
0200 if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
0201 ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
0202 ch = &sband->channels[12];
0203 if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
0204 ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
0205 return;
0206 }
0207
0208
0209
0210
0211
0212
0213
0214
0215 ch = &sband->channels[11];
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];
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
0234
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
0254
0255
0256
0257
0258
0259
0260
0261
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
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;
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
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 }