435 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright(c) 2009-2012 Realtek Corporation.*/3 4#include "wifi.h"5#include "regd.h"6 7static 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 active26 *scan on all world regulatory domains27 */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 case33 *by case basis by regulatory domain34 */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 57static 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 65static 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 74static 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 84static 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 94static 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 105static 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 116static 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 126static bool _rtl_is_radar_freq(u16 center_freq)127{128 return center_freq >= 5260 && center_freq <= 5700;129}130 131static 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 ensure159 *we enable adhoc/beaconing if it allows us to160 *use it. Note that we would have disabled it161 *by applying our static world regdomain by162 *default during init, prior to calling our163 *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 on Ch 12 and 13 */182static void _rtl_reg_apply_active_scan_flags(struct wiphy *wiphy,183 enum nl80211_reg_initiator184 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 scan196 *on these channels. This is only done for specific regulatory SKUs197 */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 this210 *channel first before enabling active scan. The passive scan211 *would have been enforced by the initial processing of our212 *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 on234 *freq range 5260 MHz - 5700 MHz235 */236static 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 this254 *frequency range. Additionally we also apply on255 *this frequency range:256 *- If STA mode does not yet have DFS supports disable257 * active scanning258 *- If adhoc mode does not support DFS yet then disable259 * adhoc in the frequency.260 *- If AP mode does not yet support radar detection/DFS261 *do not allow AP mode262 */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 270static 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 279static 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 299static 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 329static 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 349static 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 360static 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 381int 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 rtl_dbg(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 rtl_dbg(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 rtl_dbg(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 426void 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 rtl_dbg(rtlpriv, COMP_REGD, DBG_LOUD, "\n");432 433 _rtl_reg_notifier_apply(wiphy, request, &rtlpriv->regd);434}435