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