1 /******************************************************************************
3 * Copyright(c) 2009-2010 Realtek Corporation.
5 *****************************************************************************/
9 #ifdef CONFIG_IOCTL_CFG80211
11 #include <rtw_wifi_regd.h>
13 static struct country_code_to_enum_rd allCountries[] = {
14 {COUNTRY_CODE_USER, "RD"},
18 * REG_RULE(freq start, freq end, bandwidth, max gain, eirp, reg_flags)
22 *Only these channels all allow active
23 *scan on all world regulatory domains
26 /* 2G chan 01 - chan 11 */
27 #define RTW_2GHZ_CH01_11 \
28 REG_RULE(2412-10, 2462+10, 40, 0, 20, 0)
31 *We enable active scan on these a case
32 *by case basis by regulatory domain
35 /* 2G chan 12 - chan 13, PASSIV SCAN */
36 #define RTW_2GHZ_CH12_13 \
37 REG_RULE(2467-10, 2472+10, 40, 0, 20, \
38 NL80211_RRF_PASSIVE_SCAN)
40 /* 2G chan 14, PASSIVS SCAN, NO OFDM (B only) */
41 #define RTW_2GHZ_CH14 \
42 REG_RULE(2484-10, 2484+10, 40, 0, 20, \
43 NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM)
45 /* 5G chan 36 - chan 64 */
46 #define RTW_5GHZ_5150_5350 \
47 REG_RULE(5150-10, 5350+10, 40, 0, 30, \
48 NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
50 /* 5G chan 100 - chan 165 */
51 #define RTW_5GHZ_5470_5850 \
52 REG_RULE(5470-10, 5850+10, 40, 0, 30, \
53 NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
55 /* 5G chan 149 - chan 165 */
56 #define RTW_5GHZ_5725_5850 \
57 REG_RULE(5725-10, 5850+10, 40, 0, 30, \
58 NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
60 /* 5G chan 36 - chan 165 */
61 #define RTW_5GHZ_5150_5850 \
62 REG_RULE(5150-10, 5850+10, 40, 0, 30, \
63 NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
65 static const struct ieee80211_regdomain rtw_regdom_rd = {
75 static const struct ieee80211_regdomain rtw_regdom_11 = {
83 static const struct ieee80211_regdomain rtw_regdom_12_13 = {
92 static const struct ieee80211_regdomain rtw_regdom_no_midband = {
102 static const struct ieee80211_regdomain rtw_regdom_60_64 = {
112 static const struct ieee80211_regdomain rtw_regdom_14_60_64 = {
123 static const struct ieee80211_regdomain rtw_regdom_14 = {
134 static struct rtw_regulatory *rtw_regd;
137 static bool _rtw_is_radar_freq(u16 center_freq)
139 return center_freq >= 5260 && center_freq <= 5700;
143 static void _rtw_reg_apply_beaconing_flags(struct wiphy *wiphy,
144 enum nl80211_reg_initiator initiator)
146 enum ieee80211_band band;
147 struct ieee80211_supported_band *sband;
148 const struct ieee80211_reg_rule *reg_rule;
149 struct ieee80211_channel *ch;
154 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
156 if (!wiphy->bands[band])
159 sband = wiphy->bands[band];
161 for (i = 0; i < sband->n_channels; i++) {
162 ch = &sband->channels[i];
163 if (_rtw_is_radar_freq(ch->center_freq) ||
164 (ch->flags & IEEE80211_CHAN_RADAR))
166 if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
167 r = freq_reg_info(wiphy, ch->center_freq,
168 bandwidth, ®_rule);
173 *If 11d had a rule for this channel ensure
174 *we enable adhoc/beaconing if it allows us to
175 *use it. Note that we would have disabled it
176 *by applying our static world regdomain by
177 *default during init, prior to calling our
181 if (!(reg_rule->flags & NL80211_RRF_NO_IBSS))
182 ch->flags &= ~IEEE80211_CHAN_NO_IBSS;
185 NL80211_RRF_PASSIVE_SCAN))
187 ~IEEE80211_CHAN_PASSIVE_SCAN;
189 if (ch->beacon_found)
190 ch->flags &= ~(IEEE80211_CHAN_NO_IBSS |
191 IEEE80211_CHAN_PASSIVE_SCAN);
197 /* Allows active scan scan on Ch 12 and 13 */
198 static void _rtw_reg_apply_active_scan_flags(struct wiphy *wiphy,
199 enum nl80211_reg_initiator
202 struct ieee80211_supported_band *sband;
203 struct ieee80211_channel *ch;
204 const struct ieee80211_reg_rule *reg_rule;
208 if (!wiphy->bands[IEEE80211_BAND_2GHZ])
210 sband = wiphy->bands[IEEE80211_BAND_2GHZ];
213 * If no country IE has been received always enable active scan
214 * on these channels. This is only done for specific regulatory SKUs
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;
227 * If a country IE has been received 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.
233 ch = &sband->channels[11]; /* CH 12 */
234 r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_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;
241 ch = &sband->channels[12]; /* CH 13 */
242 r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_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;
252 * Always apply Radar/DFS rules on
253 * freq range 5260 MHz - 5700 MHz
255 static void _rtw_reg_apply_radar_flags(struct wiphy *wiphy)
257 struct ieee80211_supported_band *sband;
258 struct ieee80211_channel *ch;
261 if (!wiphy->bands[IEEE80211_BAND_5GHZ])
264 sband = wiphy->bands[IEEE80211_BAND_5GHZ];
266 for (i = 0; i < sband->n_channels; i++) {
267 ch = &sband->channels[i];
268 if (!_rtw_is_radar_freq(ch->center_freq))
271 #if !defined(CONFIG_DFS_MASTER)
272 if (!(ch->flags & IEEE80211_CHAN_DISABLED)) {
273 ch->flags |= IEEE80211_CHAN_RADAR;
274 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
275 ch->flags |= (IEEE80211_CHAN_NO_IBSS | IEEE80211_CHAN_PASSIVE_SCAN);
277 ch->flags |= IEEE80211_CHAN_NO_IR;
281 #endif /* CONFIG_DFS */
285 * We always enable radar detection/DFS on this
286 * frequency range. Additionally we also apply on
287 * this frequency range:
288 * - If STA mode does not yet have DFS supports disable
290 * - If adhoc mode does not support DFS yet then disable
291 * adhoc in the frequency.
292 * - If AP mode does not yet support radar detection/DFS
293 * do not allow AP mode
295 if (!(ch->flags & IEEE80211_CHAN_DISABLED))
296 ch->flags |= IEEE80211_CHAN_RADAR |
297 IEEE80211_CHAN_NO_IBSS |
298 IEEE80211_CHAN_PASSIVE_SCAN;
303 static void _rtw_reg_apply_flags(struct wiphy *wiphy)
305 #if 1 /* by channel plan */
306 _adapter *padapter = wiphy_to_adapter(wiphy);
307 u8 channel_plan = padapter->mlmepriv.ChannelPlan;
308 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
309 RT_CHANNEL_INFO *channel_set = pmlmeext->channel_set;
310 u8 max_chan_nums = pmlmeext->max_chan_nums;
312 struct ieee80211_supported_band *sband;
313 struct ieee80211_channel *ch;
318 /* all channels disable */
319 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
320 sband = wiphy->bands[i];
323 for (j = 0; j < sband->n_channels; j++) {
324 ch = &sband->channels[j];
327 ch->flags = IEEE80211_CHAN_DISABLED;
332 /* channels apply by channel plans. */
333 for (i = 0; i < max_chan_nums; i++) {
334 channel = channel_set[i].ChannelNum;
335 freq = rtw_ch2freq(channel);
337 ch = ieee80211_get_channel(wiphy, freq);
339 if (channel_set[i].ScanType == SCAN_PASSIVE) {
340 #if defined(CONFIG_DFS_MASTER)
342 #elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
343 ch->flags = (IEEE80211_CHAN_NO_IBSS | IEEE80211_CHAN_PASSIVE_SCAN);
345 ch->flags = IEEE80211_CHAN_NO_IR;
353 struct ieee80211_supported_band *sband;
354 struct ieee80211_channel *ch;
357 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56,
358 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140,
365 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
366 sband = wiphy->bands[i];
369 for (j = 0; j < sband->n_channels; j++) {
370 ch = &sband->channels[j];
373 ch->flags = IEEE80211_CHAN_DISABLED;
377 for (i = 0; i < 37; i++) {
378 channel = channels[i];
379 freq = rtw_ch2freq(channel);
381 ch = ieee80211_get_channel(wiphy, freq);
386 ch->flags = 0; /* IEEE80211_CHAN_PASSIVE_SCAN; */
388 /* printk("%s: freq %d(%d) flag 0x%02X\n", __func__, freq, channel, ch->flags); */
393 static void _rtw_reg_apply_world_flags(struct wiphy *wiphy,
394 enum nl80211_reg_initiator initiator,
395 struct rtw_regulatory *reg)
397 /* _rtw_reg_apply_beaconing_flags(wiphy, initiator); */
398 /* _rtw_reg_apply_active_scan_flags(wiphy, initiator); */
402 static int _rtw_reg_notifier_apply(struct wiphy *wiphy,
403 struct regulatory_request *request,
404 struct rtw_regulatory *reg)
407 /* Hard code flags */
408 _rtw_reg_apply_flags(wiphy);
410 /* We always apply this */
411 _rtw_reg_apply_radar_flags(wiphy);
413 switch (request->initiator) {
414 case NL80211_REGDOM_SET_BY_DRIVER:
415 RTW_INFO("%s: %s\n", __func__, "NL80211_REGDOM_SET_BY_DRIVER");
416 _rtw_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER,
419 case NL80211_REGDOM_SET_BY_CORE:
420 RTW_INFO("%s: %s\n", __func__,
421 "NL80211_REGDOM_SET_BY_CORE to DRV");
422 _rtw_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER,
425 case NL80211_REGDOM_SET_BY_USER:
426 RTW_INFO("%s: %s\n", __func__,
427 "NL80211_REGDOM_SET_BY_USER to DRV");
428 _rtw_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER,
431 case NL80211_REGDOM_SET_BY_COUNTRY_IE:
432 RTW_INFO("%s: %s\n", __func__,
433 "NL80211_REGDOM_SET_BY_COUNTRY_IE");
434 _rtw_reg_apply_world_flags(wiphy, request->initiator, reg);
441 static const struct ieee80211_regdomain *_rtw_regdomain_select(struct
446 switch (reg->country_code) {
447 case COUNTRY_CODE_USER:
449 return &rtw_regdom_rd;
452 return &rtw_regdom_rd;
456 void _rtw_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
458 struct rtw_regulatory *reg = NULL;
460 RTW_INFO("%s\n", __func__);
462 _rtw_reg_notifier_apply(wiphy, request, reg);
465 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
466 int rtw_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
468 void rtw_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
471 _rtw_reg_notifier(wiphy, request);
472 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
477 void rtw_reg_notify_by_driver(_adapter *adapter)
479 if ((adapter->rtw_wdev != NULL) && (adapter->rtw_wdev->wiphy)) {
480 struct regulatory_request request;
481 request.initiator = NL80211_REGDOM_SET_BY_DRIVER;
482 rtw_reg_notifier(adapter->rtw_wdev->wiphy, &request);
486 static void _rtw_regd_init_wiphy(struct rtw_regulatory *reg, struct wiphy *wiphy)
488 const struct ieee80211_regdomain *regd;
490 wiphy->reg_notifier = rtw_reg_notifier;
492 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
493 wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
494 wiphy->flags &= ~WIPHY_FLAG_STRICT_REGULATORY;
495 wiphy->flags &= ~WIPHY_FLAG_DISABLE_BEACON_HINTS;
497 wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
498 wiphy->regulatory_flags &= ~REGULATORY_STRICT_REG;
499 wiphy->regulatory_flags &= ~REGULATORY_DISABLE_BEACON_HINTS;
502 regd = _rtw_regdomain_select(reg);
503 wiphy_apply_custom_regulatory(wiphy, regd);
505 /* Hard code flags */
506 _rtw_reg_apply_flags(wiphy);
507 _rtw_reg_apply_radar_flags(wiphy);
508 _rtw_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg);
511 static struct country_code_to_enum_rd *_rtw_regd_find_country(u16 countrycode)
515 for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
516 if (allCountries[i].countrycode == countrycode)
517 return &allCountries[i];
522 int rtw_regd_init(_adapter *padapter)
524 struct wiphy *wiphy = padapter->rtw_wdev->wiphy;
527 if (rtw_regd == NULL) {
528 rtw_regd = (struct rtw_regulatory *)
529 rtw_malloc(sizeof(struct rtw_regulatory));
531 rtw_regd->alpha2[0] = '9';
532 rtw_regd->alpha2[1] = '9';
534 rtw_regd->country_code = COUNTRY_CODE_USER;
537 RTW_INFO("%s: Country alpha2 being used: %c%c\n",
538 __func__, rtw_regd->alpha2[0], rtw_regd->alpha2[1]);
541 _rtw_regd_init_wiphy(NULL, wiphy);
545 #endif /* CONFIG_IOCTL_CFG80211 */