Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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