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