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