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 nl80211_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[NL80211_BAND_2GHZ])
210 sband = wiphy->bands[NL80211_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[NL80211_BAND_5GHZ])
264 sband = wiphy->bands[NL80211_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 (!(ch->flags & IEEE80211_CHAN_DISABLED)
272 #if defined(CONFIG_DFS_MASTER)
273 && rtw_odm_dfs_domain_unknown(wiphy_to_adapter(wiphy))
276 ch->flags |= IEEE80211_CHAN_RADAR;
277 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
278 ch->flags |= (IEEE80211_CHAN_NO_IBSS | IEEE80211_CHAN_PASSIVE_SCAN);
280 ch->flags |= IEEE80211_CHAN_NO_IR;
283 #endif /* CONFIG_DFS */
287 * We always enable radar detection/DFS on this
288 * frequency range. Additionally we also apply on
289 * this frequency range:
290 * - If STA mode does not yet have DFS supports disable
292 * - If adhoc mode does not support DFS yet then disable
293 * adhoc in the frequency.
294 * - If AP mode does not yet support radar detection/DFS
295 * do not allow AP mode
297 if (!(ch->flags & IEEE80211_CHAN_DISABLED))
298 ch->flags |= IEEE80211_CHAN_RADAR |
299 IEEE80211_CHAN_NO_IBSS |
300 IEEE80211_CHAN_PASSIVE_SCAN;
305 static void _rtw_reg_apply_flags(struct wiphy *wiphy)
307 #if 1 /* by channel plan */
308 _adapter *padapter = wiphy_to_adapter(wiphy);
309 u8 channel_plan = padapter->mlmepriv.ChannelPlan;
310 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
311 RT_CHANNEL_INFO *channel_set = pmlmeext->channel_set;
312 u8 max_chan_nums = pmlmeext->max_chan_nums;
314 struct ieee80211_supported_band *sband;
315 struct ieee80211_channel *ch;
320 /* all channels disable */
321 for (i = 0; i < NUM_NL80211_BANDS; i++) {
322 sband = wiphy->bands[i];
325 for (j = 0; j < sband->n_channels; j++) {
326 ch = &sband->channels[j];
329 ch->flags = IEEE80211_CHAN_DISABLED;
334 /* channels apply by channel plans. */
335 for (i = 0; i < max_chan_nums; i++) {
336 channel = channel_set[i].ChannelNum;
337 freq = rtw_ch2freq(channel);
339 ch = ieee80211_get_channel(wiphy, freq);
341 if (channel_set[i].ScanType == SCAN_PASSIVE
342 #if defined(CONFIG_DFS_MASTER)
343 && rtw_odm_dfs_domain_unknown(wiphy_to_adapter(wiphy))
346 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
347 ch->flags = (IEEE80211_CHAN_NO_IBSS | IEEE80211_CHAN_PASSIVE_SCAN);
349 ch->flags = IEEE80211_CHAN_NO_IR;
357 struct ieee80211_supported_band *sband;
358 struct ieee80211_channel *ch;
361 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56,
362 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140,
369 for (i = 0; i < NUM_NL80211_BANDS; i++) {
370 sband = wiphy->bands[i];
373 for (j = 0; j < sband->n_channels; j++) {
374 ch = &sband->channels[j];
377 ch->flags = IEEE80211_CHAN_DISABLED;
381 for (i = 0; i < 37; i++) {
382 channel = channels[i];
383 freq = rtw_ch2freq(channel);
385 ch = ieee80211_get_channel(wiphy, freq);
390 ch->flags = 0; /* IEEE80211_CHAN_PASSIVE_SCAN; */
392 /* printk("%s: freq %d(%d) flag 0x%02X\n", __func__, freq, channel, ch->flags); */
397 static void _rtw_reg_apply_world_flags(struct wiphy *wiphy,
398 enum nl80211_reg_initiator initiator,
399 struct rtw_regulatory *reg)
401 /* _rtw_reg_apply_beaconing_flags(wiphy, initiator); */
402 /* _rtw_reg_apply_active_scan_flags(wiphy, initiator); */
406 static int _rtw_reg_notifier_apply(struct wiphy *wiphy,
407 struct regulatory_request *request,
408 struct rtw_regulatory *reg)
411 /* Hard code flags */
412 _rtw_reg_apply_flags(wiphy);
414 /* We always apply this */
415 _rtw_reg_apply_radar_flags(wiphy);
417 switch (request->initiator) {
418 case NL80211_REGDOM_SET_BY_DRIVER:
419 RTW_INFO("%s: %s\n", __func__, "NL80211_REGDOM_SET_BY_DRIVER");
420 _rtw_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER,
423 case NL80211_REGDOM_SET_BY_CORE:
424 RTW_INFO("%s: %s\n", __func__,
425 "NL80211_REGDOM_SET_BY_CORE to DRV");
426 _rtw_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER,
429 case NL80211_REGDOM_SET_BY_USER:
430 RTW_INFO("%s: %s\n", __func__,
431 "NL80211_REGDOM_SET_BY_USER to DRV");
432 _rtw_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER,
435 case NL80211_REGDOM_SET_BY_COUNTRY_IE:
436 RTW_INFO("%s: %s\n", __func__,
437 "NL80211_REGDOM_SET_BY_COUNTRY_IE");
438 _rtw_reg_apply_world_flags(wiphy, request->initiator, reg);
445 static const struct ieee80211_regdomain *_rtw_regdomain_select(struct
450 switch (reg->country_code) {
451 case COUNTRY_CODE_USER:
453 return &rtw_regdom_rd;
456 return &rtw_regdom_rd;
460 void _rtw_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
462 struct rtw_regulatory *reg = NULL;
464 RTW_INFO("%s\n", __func__);
466 _rtw_reg_notifier_apply(wiphy, request, reg);
469 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
470 int rtw_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
472 void rtw_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
475 _rtw_reg_notifier(wiphy, request);
476 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
481 void rtw_reg_notify_by_driver(_adapter *adapter)
483 if ((adapter->rtw_wdev != NULL) && (adapter->rtw_wdev->wiphy)) {
484 struct regulatory_request request;
485 request.initiator = NL80211_REGDOM_SET_BY_DRIVER;
486 rtw_reg_notifier(adapter->rtw_wdev->wiphy, &request);
490 static void _rtw_regd_init_wiphy(struct rtw_regulatory *reg, struct wiphy *wiphy)
492 const struct ieee80211_regdomain *regd;
494 wiphy->reg_notifier = rtw_reg_notifier;
496 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
497 wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
498 wiphy->flags &= ~WIPHY_FLAG_STRICT_REGULATORY;
499 wiphy->flags &= ~WIPHY_FLAG_DISABLE_BEACON_HINTS;
501 wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
502 wiphy->regulatory_flags &= ~REGULATORY_STRICT_REG;
503 wiphy->regulatory_flags &= ~REGULATORY_DISABLE_BEACON_HINTS;
506 regd = _rtw_regdomain_select(reg);
507 wiphy_apply_custom_regulatory(wiphy, regd);
509 /* Hard code flags */
510 _rtw_reg_apply_flags(wiphy);
511 _rtw_reg_apply_radar_flags(wiphy);
512 _rtw_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg);
515 static struct country_code_to_enum_rd *_rtw_regd_find_country(u16 countrycode)
519 for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
520 if (allCountries[i].countrycode == countrycode)
521 return &allCountries[i];
526 int rtw_regd_init(_adapter *padapter)
528 struct wiphy *wiphy = padapter->rtw_wdev->wiphy;
531 if (rtw_regd == NULL) {
532 rtw_regd = (struct rtw_regulatory *)
533 rtw_malloc(sizeof(struct rtw_regulatory));
535 rtw_regd->alpha2[0] = '9';
536 rtw_regd->alpha2[1] = '9';
538 rtw_regd->country_code = COUNTRY_CODE_USER;
541 RTW_INFO("%s: Country alpha2 being used: %c%c\n",
542 __func__, rtw_regd->alpha2[0], rtw_regd->alpha2[1]);
545 _rtw_regd_init_wiphy(NULL, wiphy);
549 #endif /* CONFIG_IOCTL_CFG80211 */