04ffe781a410fdeeaef48fb25e501c14f1a92fe6
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8723bs / os_dep / linux / wifi_regd.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2009-2010  Realtek Corporation.
4  *
5  *****************************************************************************/
6
7 #include <drv_types.h>
8
9 #ifdef CONFIG_IOCTL_CFG80211
10
11 #include <rtw_wifi_regd.h>
12
13 static struct country_code_to_enum_rd allCountries[] = {
14         {COUNTRY_CODE_USER, "RD"},
15 };
16
17 /* 
18  * REG_RULE(freq start, freq end, bandwidth, max gain, eirp, reg_flags)
19  */
20
21 /*
22  *Only these channels all allow active
23  *scan on all world regulatory domains
24  */
25
26 /* 2G chan 01 - chan 11 */
27 #define RTW_2GHZ_CH01_11        \
28         REG_RULE(2412-10, 2462+10, 40, 0, 20, 0)
29
30 /*
31  *We enable active scan on these a case
32  *by case basis by regulatory domain
33  */
34
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)
39
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)
44
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)
49
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)
54
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)
59
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)
64
65 static const struct ieee80211_regdomain rtw_regdom_rd = {
66         .n_reg_rules = 3,
67         .alpha2 = "99",
68         .reg_rules = {
69                       RTW_2GHZ_CH01_11,
70                       RTW_2GHZ_CH12_13,
71                       RTW_5GHZ_5150_5850,
72                       }
73 };
74
75 static const struct ieee80211_regdomain rtw_regdom_11 = {
76         .n_reg_rules = 1,
77         .alpha2 = "99",
78         .reg_rules = {
79                       RTW_2GHZ_CH01_11,
80                       }
81 };
82
83 static const struct ieee80211_regdomain rtw_regdom_12_13 = {
84         .n_reg_rules = 2,
85         .alpha2 = "99",
86         .reg_rules = {
87                       RTW_2GHZ_CH01_11,
88                       RTW_2GHZ_CH12_13,
89                       }
90 };
91
92 static const struct ieee80211_regdomain rtw_regdom_no_midband = {
93         .n_reg_rules = 3,
94         .alpha2 = "99",
95         .reg_rules = {
96                       RTW_2GHZ_CH01_11,
97                       RTW_5GHZ_5150_5350,
98                       RTW_5GHZ_5725_5850,
99                       }
100 };
101
102 static const struct ieee80211_regdomain rtw_regdom_60_64 = {
103         .n_reg_rules = 3,
104         .alpha2 = "99",
105         .reg_rules = {
106                       RTW_2GHZ_CH01_11,
107                       RTW_2GHZ_CH12_13,
108                       RTW_5GHZ_5725_5850,
109                       }
110 };
111
112 static const struct ieee80211_regdomain rtw_regdom_14_60_64 = {
113         .n_reg_rules = 4,
114         .alpha2 = "99",
115         .reg_rules = {
116                       RTW_2GHZ_CH01_11,
117                       RTW_2GHZ_CH12_13,
118                       RTW_2GHZ_CH14,
119                       RTW_5GHZ_5725_5850,
120                       }
121 };
122
123 static const struct ieee80211_regdomain rtw_regdom_14 = {
124         .n_reg_rules = 3,
125         .alpha2 = "99",
126         .reg_rules = {
127                       RTW_2GHZ_CH01_11,
128                       RTW_2GHZ_CH12_13,
129                       RTW_2GHZ_CH14,
130                       }
131 };
132
133 #if 0
134 static struct rtw_regulatory *rtw_regd;
135 #endif
136
137 static bool _rtw_is_radar_freq(u16 center_freq)
138 {
139         return (center_freq >= 5260 && center_freq <= 5700);
140 }
141
142 #if 0 // not_yet
143 static void _rtw_reg_apply_beaconing_flags(struct wiphy *wiphy,
144                                            enum nl80211_reg_initiator initiator)
145 {
146         enum ieee80211_band band;
147         struct ieee80211_supported_band *sband;
148         const struct ieee80211_reg_rule *reg_rule;
149         struct ieee80211_channel *ch;
150         unsigned int i;
151         u32 bandwidth = 0;
152         int r;
153
154         for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
155
156                 if (!wiphy->bands[band])
157                         continue;
158
159                 sband = wiphy->bands[band];
160
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))
165                                 continue;
166                         if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
167                                 r = freq_reg_info(wiphy, ch->center_freq,
168                                                   bandwidth, &reg_rule);
169                                 if (r)
170                                         continue;
171
172                                 /*
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
178                                  *regulatory_hint().
179                                  */
180
181                                 if (!(reg_rule->flags & NL80211_RRF_NO_IBSS))
182                                         ch->flags &= ~IEEE80211_CHAN_NO_IBSS;
183                                 if (!
184                                     (reg_rule->flags &
185                                      NL80211_RRF_PASSIVE_SCAN))
186                                         ch->flags &=
187                                             ~IEEE80211_CHAN_PASSIVE_SCAN;
188                         } else {
189                                 if (ch->beacon_found)
190                                         ch->flags &= ~(IEEE80211_CHAN_NO_IBSS |
191                                                        IEEE80211_CHAN_PASSIVE_SCAN);
192                         }
193                 }
194         }
195 }
196
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
200                                              initiator)
201 {
202         struct ieee80211_supported_band *sband;
203         struct ieee80211_channel *ch;
204         const struct ieee80211_reg_rule *reg_rule;
205         u32 bandwidth = 0;
206         int r;
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 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.
231          */
232
233         ch = &sband->channels[11];      /* CH 12 */
234         r = freq_reg_info(wiphy, ch->center_freq, bandwidth, &reg_rule);
235         if (!r) {
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         r = freq_reg_info(wiphy, ch->center_freq, bandwidth, &reg_rule);
243         if (!r) {
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 #endif
250
251 /*
252  * Always apply Radar/DFS rules on
253  * freq range 5260 MHz - 5700 MHz
254  */
255 static void _rtw_reg_apply_radar_flags(struct wiphy *wiphy)
256 {
257         struct ieee80211_supported_band *sband;
258         struct ieee80211_channel *ch;
259         unsigned int i;
260
261         if (!wiphy->bands[IEEE80211_BAND_5GHZ])
262                 return;
263
264         sband = wiphy->bands[IEEE80211_BAND_5GHZ];
265
266         for (i = 0; i < sband->n_channels; i++) {
267                 ch = &sband->channels[i];
268                 if (!_rtw_is_radar_freq(ch->center_freq))
269                         continue;
270 #ifdef CONFIG_DFS
271                 if (!(ch->flags & IEEE80211_CHAN_DISABLED)) {
272                         ch->flags |= IEEE80211_CHAN_RADAR;
273                         #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0))
274                         ch->flags |= (IEEE80211_CHAN_NO_IBSS|IEEE80211_CHAN_PASSIVE_SCAN);
275                         #else
276                         ch->flags |= IEEE80211_CHAN_NO_IR;
277                         #endif
278                 }
279 #endif //CONFIG_DFS
280
281 #if 0
282                 /*
283                  * We always enable radar detection/DFS on this
284                  * frequency range. Additionally we also apply on
285                  * this frequency range:
286                  * - If STA mode does not yet have DFS supports disable
287                  *  active scanning
288                  * - If adhoc mode does not support DFS yet then disable
289                  *  adhoc in the frequency.
290                  * - If AP mode does not yet support radar detection/DFS
291                  *  do not allow AP mode
292                  */
293                 if (!(ch->flags & IEEE80211_CHAN_DISABLED))
294                         ch->flags |= IEEE80211_CHAN_RADAR |
295                             IEEE80211_CHAN_NO_IBSS |
296                             IEEE80211_CHAN_PASSIVE_SCAN;
297 #endif
298         }
299 }
300
301 static int rtw_ieee80211_channel_to_frequency(int chan, int band)
302 {
303         /* see 802.11 17.3.8.3.2 and Annex J
304          * there are overlapping channel numbers in 5GHz and 2GHz bands */
305
306         if (band == IEEE80211_BAND_5GHZ) {
307                 if (chan >= 182 && chan <= 196)
308                         return 4000 + chan * 5;
309                 else
310                         return 5000 + chan * 5;
311         } else {                /* IEEE80211_BAND_2GHZ */
312                 if (chan == 14)
313                         return 2484;
314                 else if (chan < 14)
315                         return 2407 + chan * 5;
316                 else
317                         return 0;       /* not supported */
318         }
319 }
320
321 static void _rtw_reg_apply_flags(struct wiphy *wiphy)
322 {
323 #if 1                           // by channel plan
324         _adapter *padapter = wiphy_to_adapter(wiphy);
325         u8 channel_plan = padapter->mlmepriv.ChannelPlan;
326         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
327         RT_CHANNEL_INFO *channel_set = pmlmeext->channel_set;
328         u8 max_chan_nums = pmlmeext->max_chan_nums;
329
330         struct ieee80211_supported_band *sband;
331         struct ieee80211_channel *ch;
332         unsigned int i, j;
333         u16 channel;
334         u32 freq;
335
336         // all channels disable
337         for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
338                 sband = wiphy->bands[i];
339
340                 if (sband) {
341                         for (j = 0; j < sband->n_channels; j++) {
342                                 ch = &sband->channels[j];
343
344                                 if (ch)
345                                         ch->flags = IEEE80211_CHAN_DISABLED;
346                         }
347                 }
348         }
349
350         // channels apply by channel plans.
351         for (i = 0; i < max_chan_nums; i++) {
352                 channel = channel_set[i].ChannelNum;
353                 if (channel <= 14)
354                         freq =
355                             rtw_ieee80211_channel_to_frequency(channel,
356                                                                IEEE80211_BAND_2GHZ);
357                 else
358                         freq =
359                             rtw_ieee80211_channel_to_frequency(channel,
360                                                                IEEE80211_BAND_5GHZ);
361
362
363                 ch = ieee80211_get_channel(wiphy, freq);
364                 if (ch) {
365                         if (channel_set[i].ScanType == SCAN_PASSIVE) {
366                                 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0))
367                                 ch->flags = (IEEE80211_CHAN_NO_IBSS|IEEE80211_CHAN_PASSIVE_SCAN);
368                                 #else
369                                 ch->flags = IEEE80211_CHAN_NO_IR;
370                                 #endif
371                         }
372                         else {
373                                 ch->flags = 0;
374                         }
375                 }
376         }
377
378 #else
379         struct ieee80211_supported_band *sband;
380         struct ieee80211_channel *ch;
381         unsigned int i, j;
382         u16 channels[37] =
383             { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56,
384                 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140,
385                 149, 153,
386                 157, 161, 165
387         };
388         u16 channel;
389         u32 freq;
390
391         for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
392                 sband = wiphy->bands[i];
393
394                 if (sband)
395                         for (j = 0; j < sband->n_channels; j++) {
396                                 ch = &sband->channels[j];
397
398                                 if (ch)
399                                         ch->flags = IEEE80211_CHAN_DISABLED;
400                         }
401         }
402
403         for (i = 0; i < 37; i++) {
404                 channel = channels[i];
405                 if (channel <= 14)
406                         freq =
407                             rtw_ieee80211_channel_to_frequency(channel,
408                                                                IEEE80211_BAND_2GHZ);
409                 else
410                         freq =
411                             rtw_ieee80211_channel_to_frequency(channel,
412                                                                IEEE80211_BAND_5GHZ);
413
414                 ch = ieee80211_get_channel(wiphy, freq);
415                 if (ch) {
416                         if (channel <= 11)
417                                 ch->flags = 0;
418                         else
419                                 ch->flags = 0;  //IEEE80211_CHAN_PASSIVE_SCAN;
420                 }
421                 //printk("%s: freq %d(%d) flag 0x%02X \n", __func__, freq, channel, ch->flags);
422         }
423 #endif
424 }
425
426 static void _rtw_reg_apply_world_flags(struct wiphy *wiphy,
427                                        enum nl80211_reg_initiator initiator,
428                                        struct rtw_regulatory *reg)
429 {
430         //_rtw_reg_apply_beaconing_flags(wiphy, initiator);
431         //_rtw_reg_apply_active_scan_flags(wiphy, initiator);
432         return;
433 }
434
435 static int _rtw_reg_notifier_apply(struct wiphy *wiphy,
436                                    struct regulatory_request *request,
437                                    struct rtw_regulatory *reg)
438 {
439
440         /* Hard code flags */
441         _rtw_reg_apply_flags(wiphy);
442
443         /* We always apply this */
444         _rtw_reg_apply_radar_flags(wiphy);
445
446         switch (request->initiator) {
447         case NL80211_REGDOM_SET_BY_DRIVER:
448                 DBG_8192C("%s: %s\n", __func__, "NL80211_REGDOM_SET_BY_DRIVER");
449                 _rtw_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER,
450                                            reg);
451                 break;
452         case NL80211_REGDOM_SET_BY_CORE:
453                 DBG_8192C("%s: %s\n", __func__,
454                           "NL80211_REGDOM_SET_BY_CORE to DRV");
455                 _rtw_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER,
456                                            reg);
457                 break;
458         case NL80211_REGDOM_SET_BY_USER:
459                 DBG_8192C("%s: %s\n", __func__,
460                           "NL80211_REGDOM_SET_BY_USER to DRV");
461                 _rtw_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER,
462                                            reg);
463                 break;
464         case NL80211_REGDOM_SET_BY_COUNTRY_IE:
465                 DBG_8192C("%s: %s\n", __func__,
466                           "NL80211_REGDOM_SET_BY_COUNTRY_IE");
467                 _rtw_reg_apply_world_flags(wiphy, request->initiator, reg);
468                 break;
469         }
470
471         return 0;
472 }
473
474 static const struct ieee80211_regdomain *_rtw_regdomain_select(struct
475                                                                rtw_regulatory
476                                                                *reg)
477 {
478 #if 0
479         switch (reg->country_code) {
480         case COUNTRY_CODE_USER:
481         default:
482                 return &rtw_regdom_rd;
483         }
484 #else
485         return &rtw_regdom_rd;
486 #endif
487 }
488
489 void _rtw_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
490 {
491         struct rtw_regulatory *reg = NULL;
492
493         DBG_8192C("%s\n", __func__);
494
495         _rtw_reg_notifier_apply(wiphy, request, reg);
496 }
497
498 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0))
499 int rtw_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
500 #else
501 void rtw_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
502 #endif
503 {
504         _rtw_reg_notifier(wiphy, request);
505         #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0))
506         return 0;
507         #endif
508 }
509
510 void rtw_reg_notify_by_driver(_adapter *adapter)
511 {
512         if ((adapter->rtw_wdev != NULL) && (adapter->rtw_wdev->wiphy)) {
513                 struct regulatory_request request;
514                 request.initiator = NL80211_REGDOM_SET_BY_DRIVER;
515                 rtw_reg_notifier(adapter->rtw_wdev->wiphy, &request);
516         }
517 }
518
519 static void _rtw_regd_init_wiphy(struct rtw_regulatory *reg, struct wiphy *wiphy)
520 {
521         const struct ieee80211_regdomain *regd;
522
523         wiphy->reg_notifier = rtw_reg_notifier;
524
525         #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0))
526         wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
527         wiphy->flags &= ~WIPHY_FLAG_STRICT_REGULATORY;
528         wiphy->flags &= ~WIPHY_FLAG_DISABLE_BEACON_HINTS;
529         #else
530         wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
531         wiphy->regulatory_flags &= ~REGULATORY_STRICT_REG;
532         wiphy->regulatory_flags &= ~REGULATORY_DISABLE_BEACON_HINTS;
533         #endif
534         
535         regd = _rtw_regdomain_select(reg);
536         wiphy_apply_custom_regulatory(wiphy, regd);
537
538         /* Hard code flags */
539         _rtw_reg_apply_flags(wiphy);
540         _rtw_reg_apply_radar_flags(wiphy);
541         _rtw_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg);
542 }
543
544 static struct country_code_to_enum_rd *_rtw_regd_find_country(u16 countrycode)
545 {
546         int i;
547
548         for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
549                 if (allCountries[i].countrycode == countrycode)
550                         return &allCountries[i];
551         }
552         return NULL;
553 }
554
555 int rtw_regd_init(_adapter * padapter)
556 {
557         struct wiphy *wiphy = padapter->rtw_wdev->wiphy;
558
559 #if 0
560         if (rtw_regd == NULL) {
561                 rtw_regd = (struct rtw_regulatory *)
562                     rtw_malloc(sizeof(struct rtw_regulatory));
563
564                 rtw_regd->alpha2[0] = '9';
565                 rtw_regd->alpha2[1] = '9';
566
567                 rtw_regd->country_code = COUNTRY_CODE_USER;
568         }
569
570         DBG_8192C("%s: Country alpha2 being used: %c%c\n",
571                   __func__, rtw_regd->alpha2[0], rtw_regd->alpha2[1]);
572 #endif
573
574         _rtw_regd_init_wiphy(NULL, wiphy);
575
576         return 0;
577 }
578 #endif //CONFIG_IOCTL_CFG80211
579