staging: rtl8821ae: remove driver
[cascardo/linux.git] / drivers / staging / rtl8192ee / regd.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2009-2010  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 };
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 /*
53  *We enable active scan on these a case
54  *by case basis by regulatory domain
55  */
56 #define RTL819x_2GHZ_CH12_13    \
57         REG_RULE(2467-10, 2472+10, 40, 0, 20,\
58         NL80211_RRF_PASSIVE_SCAN)
59
60 #define RTL819x_2GHZ_CH14       \
61         REG_RULE(2484-10, 2484+10, 40, 0, 20, \
62         NL80211_RRF_PASSIVE_SCAN | \
63         NL80211_RRF_NO_OFDM)
64
65 /* 5G chan 36 - chan 64*/
66 #define RTL819x_5GHZ_5150_5350  \
67         REG_RULE(5150-10, 5350+10, 80, 0, 30, \
68         NL80211_RRF_PASSIVE_SCAN | \
69         NL80211_RRF_NO_IBSS)
70
71 /* 5G chan 100 - chan 165*/
72 #define RTL819x_5GHZ_5470_5850  \
73         REG_RULE(5470-10, 5850+10, 80, 0, 30, \
74         NL80211_RRF_PASSIVE_SCAN | \
75         NL80211_RRF_NO_IBSS)
76
77 /* 5G chan 149 - chan 165*/
78 #define RTL819x_5GHZ_5725_5850  \
79         REG_RULE(5725-10, 5850+10, 80, 0, 30, \
80         NL80211_RRF_PASSIVE_SCAN | \
81         NL80211_RRF_NO_IBSS)
82
83 #define RTL819x_5GHZ_ALL        \
84         (RTL819x_5GHZ_5150_5350, RTL819x_5GHZ_5470_5850)
85
86 static const struct ieee80211_regdomain rtl_regdom_11 = {
87         .n_reg_rules = 1,
88         .alpha2 = "99",
89         .reg_rules = {
90                       RTL819x_2GHZ_CH01_11,
91                       }
92 };
93
94 static const struct ieee80211_regdomain rtl_regdom_12_13 = {
95         .n_reg_rules = 2,
96         .alpha2 = "99",
97         .reg_rules = {
98                       RTL819x_2GHZ_CH01_11,
99                           RTL819x_2GHZ_CH12_13,
100                       }
101 };
102
103 static const struct ieee80211_regdomain rtl_regdom_no_midband = {
104         .n_reg_rules = 3,
105         .alpha2 = "99",
106         .reg_rules = {
107                       RTL819x_2GHZ_CH01_11,
108                           RTL819x_5GHZ_5150_5350,
109                           RTL819x_5GHZ_5725_5850,
110                       }
111 };
112
113 static const struct ieee80211_regdomain rtl_regdom_60_64 = {
114         .n_reg_rules = 3,
115         .alpha2 = "99",
116         .reg_rules = {
117                       RTL819x_2GHZ_CH01_11,
118                           RTL819x_2GHZ_CH12_13,
119                           RTL819x_5GHZ_5725_5850,
120                       }
121 };
122
123 static const struct ieee80211_regdomain rtl_regdom_14_60_64 = {
124         .n_reg_rules = 4,
125         .alpha2 = "99",
126         .reg_rules = {
127                       RTL819x_2GHZ_CH01_11,
128                           RTL819x_2GHZ_CH12_13,
129                           RTL819x_2GHZ_CH14,
130                           RTL819x_5GHZ_5725_5850,
131                       }
132 };
133
134 static const struct ieee80211_regdomain rtl_regdom_14 = {
135         .n_reg_rules = 3,
136         .alpha2 = "99",
137         .reg_rules = {
138                       RTL819x_2GHZ_CH01_11,
139                           RTL819x_2GHZ_CH12_13,
140                           RTL819x_2GHZ_CH14,
141                       }
142 };
143
144 static bool _rtl_is_radar_freq(u16 center_freq)
145 {
146         return center_freq >= 5260 && center_freq <= 5700;
147 }
148
149 static void _rtl_reg_apply_beaconing_flags(struct wiphy *wiphy,
150                                            enum nl80211_reg_initiator initiator)
151 {
152         enum ieee80211_band band;
153         struct ieee80211_supported_band *sband;
154         const struct ieee80211_reg_rule *reg_rule;
155         struct ieee80211_channel *ch;
156         unsigned int i;
157
158         for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
159                 if (!wiphy->bands[band])
160                         continue;
161
162                 sband = wiphy->bands[band];
163
164                 for (i = 0; i < sband->n_channels; i++) {
165                         ch = &sband->channels[i];
166                         if (_rtl_is_radar_freq(ch->center_freq) ||
167                             (ch->flags & IEEE80211_CHAN_RADAR))
168                                 continue;
169                         if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
170                                 reg_rule = freq_reg_info(wiphy,
171                                                          ch->center_freq);
172                                 if (IS_ERR(reg_rule))
173                                         continue;
174
175                                 /*
176                                  *If 11d had a rule for this channel ensure
177                                  *we enable adhoc/beaconing if it allows us to
178                                  *use it. Note that we would have disabled it
179                                  *by applying our static world regdomain by
180                                  *default during init, prior to calling our
181                                  *regulatory_hint().
182                                  */
183
184                                 if (!(reg_rule->flags & NL80211_RRF_NO_IBSS))
185                                         ch->flags &= ~IEEE80211_CHAN_NO_IBSS;
186                                 if (!(reg_rule->flags &
187                                       NL80211_RRF_PASSIVE_SCAN))
188                                         ch->flags &=
189                                             ~IEEE80211_CHAN_PASSIVE_SCAN;
190                         } else {
191                                 if (ch->beacon_found)
192                                         ch->flags &= ~(IEEE80211_CHAN_NO_IBSS |
193                                                    IEEE80211_CHAN_PASSIVE_SCAN);
194                         }
195                 }
196         }
197 }
198
199 /* Allows active scan scan on Ch 12 and 13 */
200 static void _rtl_reg_apply_active_scan_flags(struct wiphy *wiphy,
201                                              enum nl80211_reg_initiator
202                                              initiator)
203 {
204         struct ieee80211_supported_band *sband;
205         struct ieee80211_channel *ch;
206         const struct ieee80211_reg_rule *reg_rule;
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 recieved 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[IEEE80211_BAND_5GHZ])
261                 return;
262
263         sband = wiphy->bands[IEEE80211_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 ieee80211_band band;
299         struct ieee80211_supported_band *sband;
300         struct ieee80211_channel *ch;
301         unsigned int i;
302
303         for (band = 0; band < IEEE80211_NUM_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 _rtl92e_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_ETSI:
343         case COUNTRY_CODE_TELEC_NETGEAR:
344                 return &rtl_regdom_60_64;
345         case COUNTRY_CODE_SPAIN:
346         case COUNTRY_CODE_FRANCE:
347         case COUNTRY_CODE_ISRAEL:
348         case COUNTRY_CODE_WORLD_WIDE_13:
349                 return &rtl_regdom_12_13;
350         case COUNTRY_CODE_MKK:
351         case COUNTRY_CODE_MKK1:
352         case COUNTRY_CODE_TELEC:
353         case COUNTRY_CODE_MIC:
354                 return &rtl_regdom_14_60_64;
355         case COUNTRY_CODE_GLOBAL_DOMAIN:
356                 return &rtl_regdom_14;
357         default:
358                 return &rtl_regdom_no_midband;
359         }
360 }
361
362 static int
363 _rtl92e_regd_init_wiphy(struct rtl_regulatory *reg,
364                         struct wiphy *wiphy,
365                         void (*reg_notifier)(struct wiphy *wiphy,
366                                              struct regulatory_request *req))
367 {
368         const struct ieee80211_regdomain *regd;
369
370         wiphy->reg_notifier = reg_notifier;
371
372         wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
373         wiphy->regulatory_flags &= ~REGULATORY_STRICT_REG;
374         wiphy->regulatory_flags &= ~REGULATORY_DISABLE_BEACON_HINTS;
375
376         regd = _rtl_regdomain_select(reg);
377         wiphy_apply_custom_regulatory(wiphy, regd);
378         _rtl_reg_apply_radar_flags(wiphy);
379         _rtl_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg);
380         return 0;
381 }
382
383 static struct country_code_to_enum_rd *_rtl_regd_find_country(u16 countrycode)
384 {
385         int i;
386
387         for (i = 0; i < ARRAY_SIZE(allcountries); i++) {
388                 if (allcountries[i].countrycode == countrycode)
389                         return &allcountries[i];
390         }
391         return NULL;
392 }
393
394 int rtl92e_regd_init(struct ieee80211_hw *hw,
395                      void (*reg_notifier)(struct wiphy *wiphy,
396                                           struct regulatory_request *request))
397 {
398         struct rtl_priv *rtlpriv = rtl_priv(hw);
399         struct wiphy *wiphy = hw->wiphy;
400         struct country_code_to_enum_rd *country = NULL;
401
402         if (wiphy == NULL || &rtlpriv->regd == NULL)
403                 return -EINVAL;
404
405         /* init country_code from efuse channel plan */
406         rtlpriv->regd.country_code = rtlpriv->efuse.channel_plan;
407
408         RT_TRACE(COMP_REGD, DBG_TRACE,
409                  KERN_DEBUG "rtl: EEPROM regdomain: 0x%0x\n",
410                   rtlpriv->regd.country_code);
411
412         if (rtlpriv->regd.country_code >= COUNTRY_CODE_MAX) {
413                 RT_TRACE(COMP_REGD, DBG_DMESG,
414                          "rtl: EEPROM indicates invalid contry code world wide 13 should be used\n");
415
416                 rtlpriv->regd.country_code = COUNTRY_CODE_WORLD_WIDE_13;
417         }
418
419         country = _rtl_regd_find_country(rtlpriv->regd.country_code);
420
421         if (country) {
422                 rtlpriv->regd.alpha2[0] = country->iso_name[0];
423                 rtlpriv->regd.alpha2[1] = country->iso_name[1];
424         } else {
425                 rtlpriv->regd.alpha2[0] = '0';
426                 rtlpriv->regd.alpha2[1] = '0';
427         }
428
429         RT_TRACE(COMP_REGD, DBG_TRACE,
430                  KERN_DEBUG "rtl: Country alpha2 being used: %c%c\n",
431                   rtlpriv->regd.alpha2[0], rtlpriv->regd.alpha2[1]);
432
433         _rtl92e_regd_init_wiphy(&rtlpriv->regd, wiphy, reg_notifier);
434
435         return 0;
436 }
437
438 void rtl92e_reg_notifier(struct wiphy *wiphy,
439                          struct regulatory_request *request)
440 {
441         struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
442         struct rtl_priv *rtlpriv = rtl_priv(hw);
443
444         RT_TRACE(COMP_REGD, DBG_LOUD, "\n");
445
446         _rtl92e_reg_notifier_apply(wiphy, request, &rtlpriv->regd);
447 }