Linux-libre 4.14.68-gnu
[librecmc/linux-libre.git] / drivers / staging / rtlwifi / regd.c
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  * 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
29 static 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         {COUNTRY_CODE_WORLD_WIDE_13_5G_ALL, "US"},
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 /*We enable active scan on these a case
53  *by case basis by regulatory domain
54  */
55 #define RTL819x_2GHZ_CH12_13    \
56         REG_RULE(2467 - 10, 2472 + 10, 40, 0, 20,\
57         NL80211_RRF_PASSIVE_SCAN)
58
59 #define RTL819x_2GHZ_CH14       \
60         REG_RULE(2484 - 10, 2484 + 10, 40, 0, 20, \
61         NL80211_RRF_PASSIVE_SCAN | \
62         NL80211_RRF_NO_OFDM)
63
64 /* 5G chan 36 - chan 64*/
65 #define RTL819x_5GHZ_5150_5350  \
66         REG_RULE(5150 - 10, 5350 + 10, 80, 0, 30, 0)
67 /* 5G chan 100 - chan 165*/
68 #define RTL819x_5GHZ_5470_5850  \
69         REG_RULE(5470 - 10, 5850 + 10, 80, 0, 30, 0)
70 /* 5G chan 149 - chan 165*/
71 #define RTL819x_5GHZ_5725_5850  \
72         REG_RULE(5725 - 10, 5850 + 10, 80, 0, 30, 0)
73
74 #define RTL819x_5GHZ_ALL        \
75         (RTL819x_5GHZ_5150_5350, RTL819x_5GHZ_5470_5850)
76
77 static const struct ieee80211_regdomain rtl_regdom_11 = {
78         .n_reg_rules = 1,
79         .alpha2 = "99",
80         .reg_rules = {
81                 RTL819x_2GHZ_CH01_11,
82         }
83 };
84
85 static const struct ieee80211_regdomain rtl_regdom_12_13 = {
86         .n_reg_rules = 2,
87         .alpha2 = "99",
88         .reg_rules = {
89                 RTL819x_2GHZ_CH01_11,
90                 RTL819x_2GHZ_CH12_13,
91         }
92 };
93
94 static const struct ieee80211_regdomain rtl_regdom_no_midband = {
95         .n_reg_rules = 3,
96         .alpha2 = "99",
97         .reg_rules = {
98                 RTL819x_2GHZ_CH01_11,
99                 RTL819x_5GHZ_5150_5350,
100                 RTL819x_5GHZ_5725_5850,
101         }
102 };
103
104 static const struct ieee80211_regdomain rtl_regdom_60_64 = {
105         .n_reg_rules = 3,
106         .alpha2 = "99",
107         .reg_rules = {
108                 RTL819x_2GHZ_CH01_11,
109                 RTL819x_2GHZ_CH12_13,
110                 RTL819x_5GHZ_5725_5850,
111         }
112 };
113
114 static const struct ieee80211_regdomain rtl_regdom_14_60_64 = {
115         .n_reg_rules = 4,
116         .alpha2 = "99",
117         .reg_rules = {
118                 RTL819x_2GHZ_CH01_11,
119                 RTL819x_2GHZ_CH12_13,
120                 RTL819x_2GHZ_CH14,
121                 RTL819x_5GHZ_5725_5850,
122         }
123 };
124
125 static const struct ieee80211_regdomain rtl_regdom_12_13_5g_all = {
126         .n_reg_rules = 4,
127         .alpha2 = "99",
128         .reg_rules = {
129                 RTL819x_2GHZ_CH01_11,
130                 RTL819x_2GHZ_CH12_13,
131                 RTL819x_5GHZ_5150_5350,
132                 RTL819x_5GHZ_5470_5850,
133         }
134 };
135
136 static const struct ieee80211_regdomain rtl_regdom_14 = {
137         .n_reg_rules = 3,
138         .alpha2 = "99",
139         .reg_rules = {
140                 RTL819x_2GHZ_CH01_11,
141                 RTL819x_2GHZ_CH12_13,
142                 RTL819x_2GHZ_CH14,
143         }
144 };
145
146 static bool _rtl_is_radar_freq(u16 center_freq)
147 {
148         return center_freq >= 5260 && center_freq <= 5700;
149 }
150
151 static void _rtl_reg_apply_beaconing_flags(struct wiphy *wiphy,
152                                            enum nl80211_reg_initiator initiator)
153 {
154         enum nl80211_band band;
155         struct ieee80211_supported_band *sband;
156         const struct ieee80211_reg_rule *reg_rule;
157         struct ieee80211_channel *ch;
158         unsigned int i;
159
160         for (band = 0; band < NUM_NL80211_BANDS; band++) {
161                 if (!wiphy->bands[band])
162                         continue;
163
164                 sband = wiphy->bands[band];
165
166                 for (i = 0; i < sband->n_channels; i++) {
167                         ch = &sband->channels[i];
168                         if (_rtl_is_radar_freq(ch->center_freq) ||
169                             (ch->flags & IEEE80211_CHAN_RADAR))
170                                 continue;
171                         if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
172                                 reg_rule = freq_reg_info(wiphy,
173                                                          ch->center_freq);
174                                 if (IS_ERR(reg_rule))
175                                         continue;
176                                 /*
177                                  *If 11d had a rule for this channel ensure
178                                  *we enable adhoc/beaconing if it allows us to
179                                  *use it. Note that we would have disabled it
180                                  *by applying our static world regdomain by
181                                  *default during init, prior to calling our
182                                  *regulatory_hint().
183                                  */
184
185                                 if (!(reg_rule->flags & NL80211_RRF_NO_IBSS))
186                                         ch->flags &= ~IEEE80211_CHAN_NO_IBSS;
187                                 if (!(reg_rule->flags &
188                                       NL80211_RRF_PASSIVE_SCAN))
189                                         ch->flags &=
190                                             ~IEEE80211_CHAN_PASSIVE_SCAN;
191                         } else {
192                                 if (ch->beacon_found)
193                                         ch->flags &= ~(IEEE80211_CHAN_NO_IBSS |
194                                                    IEEE80211_CHAN_PASSIVE_SCAN);
195                         }
196                 }
197         }
198 }
199
200 /* Allows active scan scan on Ch 12 and 13 */
201 static void _rtl_reg_apply_active_scan_flags(struct wiphy *wiphy,
202                                              enum nl80211_reg_initiator
203                                              initiator)
204 {
205         struct ieee80211_supported_band *sband;
206         struct ieee80211_channel *ch;
207         const struct ieee80211_reg_rule *reg_rule;
208
209         if (!wiphy->bands[NL80211_BAND_2GHZ])
210                 return;
211         sband = wiphy->bands[NL80211_BAND_2GHZ];
212
213         /*
214          *If no country IE has been received always enable active scan
215          *on these channels. This is only done for specific regulatory SKUs
216          */
217         if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
218                 ch = &sband->channels[11];      /* CH 12 */
219                 if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
220                         ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
221                 ch = &sband->channels[12];      /* CH 13 */
222                 if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
223                         ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
224                 return;
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         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  */
254 static 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[NL80211_BAND_5GHZ])
261                 return;
262
263         sband = wiphy->bands[NL80211_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
288 static 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 }
295
296 static void _rtl_dump_channel_map(struct wiphy *wiphy)
297 {
298         enum nl80211_band band;
299         struct ieee80211_supported_band *sband;
300         struct ieee80211_channel *ch;
301         unsigned int i;
302
303         for (band = 0; band < NUM_NL80211_BANDS; band++) {
304                 if (!wiphy->bands[band])
305                         continue;
306                 sband = wiphy->bands[band];
307                 for (i = 0; i < sband->n_channels; i++)
308                         ch = &sband->channels[i];
309         }
310 }
311
312 static int _rtl_reg_notifier_apply(struct wiphy *wiphy,
313                                    struct regulatory_request *request,
314                                    struct rtl_regulatory *reg)
315 {
316         /* We always apply this */
317         _rtl_reg_apply_radar_flags(wiphy);
318
319         switch (request->initiator) {
320         case NL80211_REGDOM_SET_BY_DRIVER:
321         case NL80211_REGDOM_SET_BY_CORE:
322         case NL80211_REGDOM_SET_BY_USER:
323                 break;
324         case NL80211_REGDOM_SET_BY_COUNTRY_IE:
325                 _rtl_reg_apply_world_flags(wiphy, request->initiator, reg);
326                 break;
327         }
328
329         _rtl_dump_channel_map(wiphy);
330
331         return 0;
332 }
333
334 static const struct ieee80211_regdomain *_rtl_regdomain_select(
335                                                 struct rtl_regulatory *reg)
336 {
337         switch (reg->country_code) {
338         case COUNTRY_CODE_FCC:
339                 return &rtl_regdom_no_midband;
340         case COUNTRY_CODE_IC:
341                 return &rtl_regdom_11;
342         case COUNTRY_CODE_TELEC_NETGEAR:
343                 return &rtl_regdom_60_64;
344         case COUNTRY_CODE_ETSI:
345         case COUNTRY_CODE_SPAIN:
346         case COUNTRY_CODE_FRANCE:
347         case COUNTRY_CODE_ISRAEL:
348                 return &rtl_regdom_12_13;
349         case COUNTRY_CODE_MKK:
350         case COUNTRY_CODE_MKK1:
351         case COUNTRY_CODE_TELEC:
352         case COUNTRY_CODE_MIC:
353                 return &rtl_regdom_14_60_64;
354         case COUNTRY_CODE_GLOBAL_DOMAIN:
355                 return &rtl_regdom_14;
356         case COUNTRY_CODE_WORLD_WIDE_13:
357         case COUNTRY_CODE_WORLD_WIDE_13_5G_ALL:
358                 return &rtl_regdom_12_13_5g_all;
359         default:
360                 return &rtl_regdom_no_midband;
361         }
362 }
363
364 static int _rtl_regd_init_wiphy(struct rtl_regulatory *reg,
365                                 struct wiphy *wiphy,
366                                 void (*reg_notifier)(struct wiphy *wiphy,
367                                                      struct regulatory_request *
368                                                      request))
369 {
370         const struct ieee80211_regdomain *regd;
371
372         wiphy->reg_notifier = reg_notifier;
373
374         wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
375         wiphy->regulatory_flags &= ~REGULATORY_STRICT_REG;
376         wiphy->regulatory_flags &= ~REGULATORY_DISABLE_BEACON_HINTS;
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
384 static 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
395 static u8 channel_plan_to_country_code(u8 channelplan)
396 {
397         switch (channelplan) {
398         case 0x20:
399         case 0x21:
400                 return COUNTRY_CODE_WORLD_WIDE_13;
401         case 0x22:
402                 return COUNTRY_CODE_IC;
403         case 0x25:
404                 return COUNTRY_CODE_ETSI;
405         case 0x32:
406                 return COUNTRY_CODE_TELEC_NETGEAR;
407         case 0x41:
408                 return COUNTRY_CODE_GLOBAL_DOMAIN;
409         case 0x7f:
410                 return COUNTRY_CODE_WORLD_WIDE_13_5G_ALL;
411         default:
412                 return COUNTRY_CODE_MAX; /*Error*/
413         }
414 }
415
416 int rtl_regd_init(struct ieee80211_hw *hw,
417                   void (*reg_notifier)(struct wiphy *wiphy,
418                                        struct regulatory_request *request))
419 {
420         struct rtl_priv *rtlpriv = rtl_priv(hw);
421         struct wiphy *wiphy = hw->wiphy;
422         struct country_code_to_enum_rd *country = NULL;
423
424         if (!wiphy || !&rtlpriv->regd)
425                 return -EINVAL;
426
427         /* init country_code from efuse channel plan */
428         rtlpriv->regd.country_code =
429                 channel_plan_to_country_code(rtlpriv->efuse.channel_plan);
430
431         RT_TRACE(rtlpriv, COMP_REGD, DBG_DMESG,
432                  "rtl: EEPROM regdomain: 0x%0x country code: %d\n",
433                  rtlpriv->efuse.channel_plan, rtlpriv->regd.country_code);
434
435         if (rtlpriv->regd.country_code >= COUNTRY_CODE_MAX) {
436                 RT_TRACE(rtlpriv, COMP_REGD, DBG_DMESG,
437                          "rtl: EEPROM indicates invalid country code, world wide 13 should be used\n");
438
439                 rtlpriv->regd.country_code = COUNTRY_CODE_WORLD_WIDE_13;
440         }
441
442         country = _rtl_regd_find_country(rtlpriv->regd.country_code);
443
444         if (country) {
445                 rtlpriv->regd.alpha2[0] = country->iso_name[0];
446                 rtlpriv->regd.alpha2[1] = country->iso_name[1];
447         } else {
448                 rtlpriv->regd.alpha2[0] = '0';
449                 rtlpriv->regd.alpha2[1] = '0';
450         }
451
452         RT_TRACE(rtlpriv, COMP_REGD, DBG_TRACE,
453                  "rtl: Country alpha2 being used: %c%c\n",
454                   rtlpriv->regd.alpha2[0], rtlpriv->regd.alpha2[1]);
455
456         _rtl_regd_init_wiphy(&rtlpriv->regd, wiphy, reg_notifier);
457
458         return 0;
459 }
460
461 void rtl_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
462 {
463         struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
464         struct rtl_priv *rtlpriv = rtl_priv(hw);
465
466         RT_TRACE(rtlpriv, COMP_REGD, DBG_LOUD, "\n");
467
468         _rtl_reg_notifier_apply(wiphy, request, &rtlpriv->regd);
469 }