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