regd.c (11430B)
1// SPDX-License-Identifier: GPL-2.0 2/* 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 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 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 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 */ 182static 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 */ 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 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 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}