cfg80211: remove enum ieee80211_band
[cascardo/linux.git] / drivers / net / wireless / broadcom / brcm80211 / brcmsmac / channel.c
1 /*
2  * Copyright (c) 2010 Broadcom Corporation
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include <linux/types.h>
18 #include <net/cfg80211.h>
19 #include <net/mac80211.h>
20 #include <net/regulatory.h>
21
22 #include <defs.h>
23 #include "pub.h"
24 #include "phy/phy_hal.h"
25 #include "main.h"
26 #include "stf.h"
27 #include "channel.h"
28 #include "mac80211_if.h"
29 #include "debug.h"
30
31 /* QDB() macro takes a dB value and converts to a quarter dB value */
32 #define QDB(n) ((n) * BRCMS_TXPWR_DB_FACTOR)
33
34 #define LOCALE_MIMO_IDX_bn              0
35 #define LOCALE_MIMO_IDX_11n             0
36
37 /* max of BAND_5G_PWR_LVLS and 14 for 2.4 GHz */
38 #define BRCMS_MAXPWR_MIMO_TBL_SIZE      14
39
40 /* maxpwr mapping to 5GHz band channels:
41  * maxpwr[0] - channels [34-48]
42  * maxpwr[1] - channels [52-60]
43  * maxpwr[2] - channels [62-64]
44  * maxpwr[3] - channels [100-140]
45  * maxpwr[4] - channels [149-165]
46  */
47 #define BAND_5G_PWR_LVLS        5       /* 5 power levels for 5G */
48
49 #define LC(id)  LOCALE_MIMO_IDX_ ## id
50
51 #define LOCALES(mimo2, mimo5) \
52                 {LC(mimo2), LC(mimo5)}
53
54 /* macro to get 5 GHz channel group index for tx power */
55 #define CHANNEL_POWER_IDX_5G(c) (((c) < 52) ? 0 : \
56                                  (((c) < 62) ? 1 : \
57                                  (((c) < 100) ? 2 : \
58                                  (((c) < 149) ? 3 : 4))))
59
60 #define BRCM_2GHZ_2412_2462     REG_RULE(2412-10, 2462+10, 40, 0, 19, 0)
61 #define BRCM_2GHZ_2467_2472     REG_RULE(2467-10, 2472+10, 20, 0, 19, \
62                                          NL80211_RRF_NO_IR)
63
64 #define BRCM_5GHZ_5180_5240     REG_RULE(5180-10, 5240+10, 40, 0, 21, \
65                                          NL80211_RRF_NO_IR)
66 #define BRCM_5GHZ_5260_5320     REG_RULE(5260-10, 5320+10, 40, 0, 21, \
67                                          NL80211_RRF_DFS | \
68                                          NL80211_RRF_NO_IR)
69 #define BRCM_5GHZ_5500_5700     REG_RULE(5500-10, 5700+10, 40, 0, 21, \
70                                          NL80211_RRF_DFS | \
71                                          NL80211_RRF_NO_IR)
72 #define BRCM_5GHZ_5745_5825     REG_RULE(5745-10, 5825+10, 40, 0, 21, \
73                                          NL80211_RRF_NO_IR)
74
75 static const struct ieee80211_regdomain brcms_regdom_x2 = {
76         .n_reg_rules = 6,
77         .alpha2 = "X2",
78         .reg_rules = {
79                 BRCM_2GHZ_2412_2462,
80                 BRCM_2GHZ_2467_2472,
81                 BRCM_5GHZ_5180_5240,
82                 BRCM_5GHZ_5260_5320,
83                 BRCM_5GHZ_5500_5700,
84                 BRCM_5GHZ_5745_5825,
85         }
86 };
87
88  /* locale per-channel tx power limits for MIMO frames
89   * maxpwr arrays are index by channel for 2.4 GHz limits, and
90   * by sub-band for 5 GHz limits using CHANNEL_POWER_IDX_5G(channel)
91   */
92 struct locale_mimo_info {
93         /* tx 20 MHz power limits, qdBm units */
94         s8 maxpwr20[BRCMS_MAXPWR_MIMO_TBL_SIZE];
95         /* tx 40 MHz power limits, qdBm units */
96         s8 maxpwr40[BRCMS_MAXPWR_MIMO_TBL_SIZE];
97 };
98
99 /* Country names and abbreviations with locale defined from ISO 3166 */
100 struct country_info {
101         const u8 locale_mimo_2G;        /* 2.4G mimo info */
102         const u8 locale_mimo_5G;        /* 5G mimo info */
103 };
104
105 struct brcms_regd {
106         struct country_info country;
107         const struct ieee80211_regdomain *regdomain;
108 };
109
110 struct brcms_cm_info {
111         struct brcms_pub *pub;
112         struct brcms_c_info *wlc;
113         const struct brcms_regd *world_regd;
114 };
115
116 /*
117  * MIMO Locale Definitions - 2.4 GHz
118  */
119 static const struct locale_mimo_info locale_bn = {
120         {QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
121          QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
122          QDB(13), QDB(13), QDB(13)},
123         {0, 0, QDB(13), QDB(13), QDB(13),
124          QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
125          QDB(13), 0, 0},
126 };
127
128 static const struct locale_mimo_info *g_mimo_2g_table[] = {
129         &locale_bn
130 };
131
132 /*
133  * MIMO Locale Definitions - 5 GHz
134  */
135 static const struct locale_mimo_info locale_11n = {
136         { /* 12.5 dBm */ 50, 50, 50, QDB(15), QDB(15)},
137         {QDB(14), QDB(15), QDB(15), QDB(15), QDB(15)},
138 };
139
140 static const struct locale_mimo_info *g_mimo_5g_table[] = {
141         &locale_11n
142 };
143
144 static const struct brcms_regd cntry_locales[] = {
145         /* Worldwide RoW 2, must always be at index 0 */
146         {
147                 .country = LOCALES(bn, 11n),
148                 .regdomain = &brcms_regdom_x2,
149         },
150 };
151
152 static const struct locale_mimo_info *brcms_c_get_mimo_2g(u8 locale_idx)
153 {
154         if (locale_idx >= ARRAY_SIZE(g_mimo_2g_table))
155                 return NULL;
156
157         return g_mimo_2g_table[locale_idx];
158 }
159
160 static const struct locale_mimo_info *brcms_c_get_mimo_5g(u8 locale_idx)
161 {
162         if (locale_idx >= ARRAY_SIZE(g_mimo_5g_table))
163                 return NULL;
164
165         return g_mimo_5g_table[locale_idx];
166 }
167
168 /*
169  * Indicates whether the country provided is valid to pass
170  * to cfg80211 or not.
171  *
172  * returns true if valid; false if not.
173  */
174 static bool brcms_c_country_valid(const char *ccode)
175 {
176         /*
177          * only allow ascii alpha uppercase for the first 2
178          * chars.
179          */
180         if (!((ccode[0] & 0x80) == 0 && ccode[0] >= 0x41 && ccode[0] <= 0x5A &&
181               (ccode[1] & 0x80) == 0 && ccode[1] >= 0x41 && ccode[1] <= 0x5A))
182                 return false;
183
184         /*
185          * do not match ISO 3166-1 user assigned country codes
186          * that may be in the driver table
187          */
188         if (!strcmp("AA", ccode) ||        /* AA */
189             !strcmp("ZZ", ccode) ||        /* ZZ */
190             ccode[0] == 'X' ||             /* XA - XZ */
191             (ccode[0] == 'Q' &&            /* QM - QZ */
192              (ccode[1] >= 'M' && ccode[1] <= 'Z')))
193                 return false;
194
195         if (!strcmp("NA", ccode))
196                 return false;
197
198         return true;
199 }
200
201 static const struct brcms_regd *brcms_world_regd(const char *regdom, int len)
202 {
203         const struct brcms_regd *regd = NULL;
204         int i;
205
206         for (i = 0; i < ARRAY_SIZE(cntry_locales); i++) {
207                 if (!strncmp(regdom, cntry_locales[i].regdomain->alpha2, len)) {
208                         regd = &cntry_locales[i];
209                         break;
210                 }
211         }
212
213         return regd;
214 }
215
216 static const struct brcms_regd *brcms_default_world_regd(void)
217 {
218         return &cntry_locales[0];
219 }
220
221 /* JP, J1 - J10 are Japan ccodes */
222 static bool brcms_c_japan_ccode(const char *ccode)
223 {
224         return (ccode[0] == 'J' &&
225                 (ccode[1] == 'P' || (ccode[1] >= '1' && ccode[1] <= '9')));
226 }
227
228 static void
229 brcms_c_channel_min_txpower_limits_with_local_constraint(
230                 struct brcms_cm_info *wlc_cm, struct txpwr_limits *txpwr,
231                 u8 local_constraint_qdbm)
232 {
233         int j;
234
235         /* CCK Rates */
236         for (j = 0; j < WL_TX_POWER_CCK_NUM; j++)
237                 txpwr->cck[j] = min(txpwr->cck[j], local_constraint_qdbm);
238
239         /* 20 MHz Legacy OFDM SISO */
240         for (j = 0; j < WL_TX_POWER_OFDM_NUM; j++)
241                 txpwr->ofdm[j] = min(txpwr->ofdm[j], local_constraint_qdbm);
242
243         /* 20 MHz Legacy OFDM CDD */
244         for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++)
245                 txpwr->ofdm_cdd[j] =
246                     min(txpwr->ofdm_cdd[j], local_constraint_qdbm);
247
248         /* 40 MHz Legacy OFDM SISO */
249         for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++)
250                 txpwr->ofdm_40_siso[j] =
251                     min(txpwr->ofdm_40_siso[j], local_constraint_qdbm);
252
253         /* 40 MHz Legacy OFDM CDD */
254         for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++)
255                 txpwr->ofdm_40_cdd[j] =
256                     min(txpwr->ofdm_40_cdd[j], local_constraint_qdbm);
257
258         /* 20MHz MCS 0-7 SISO */
259         for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
260                 txpwr->mcs_20_siso[j] =
261                     min(txpwr->mcs_20_siso[j], local_constraint_qdbm);
262
263         /* 20MHz MCS 0-7 CDD */
264         for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
265                 txpwr->mcs_20_cdd[j] =
266                     min(txpwr->mcs_20_cdd[j], local_constraint_qdbm);
267
268         /* 20MHz MCS 0-7 STBC */
269         for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
270                 txpwr->mcs_20_stbc[j] =
271                     min(txpwr->mcs_20_stbc[j], local_constraint_qdbm);
272
273         /* 20MHz MCS 8-15 MIMO */
274         for (j = 0; j < BRCMS_NUM_RATES_MCS_2_STREAM; j++)
275                 txpwr->mcs_20_mimo[j] =
276                     min(txpwr->mcs_20_mimo[j], local_constraint_qdbm);
277
278         /* 40MHz MCS 0-7 SISO */
279         for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
280                 txpwr->mcs_40_siso[j] =
281                     min(txpwr->mcs_40_siso[j], local_constraint_qdbm);
282
283         /* 40MHz MCS 0-7 CDD */
284         for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
285                 txpwr->mcs_40_cdd[j] =
286                     min(txpwr->mcs_40_cdd[j], local_constraint_qdbm);
287
288         /* 40MHz MCS 0-7 STBC */
289         for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
290                 txpwr->mcs_40_stbc[j] =
291                     min(txpwr->mcs_40_stbc[j], local_constraint_qdbm);
292
293         /* 40MHz MCS 8-15 MIMO */
294         for (j = 0; j < BRCMS_NUM_RATES_MCS_2_STREAM; j++)
295                 txpwr->mcs_40_mimo[j] =
296                     min(txpwr->mcs_40_mimo[j], local_constraint_qdbm);
297
298         /* 40MHz MCS 32 */
299         txpwr->mcs32 = min(txpwr->mcs32, local_constraint_qdbm);
300
301 }
302
303 /*
304  * set the driver's current country and regulatory information
305  * using a country code as the source. Look up built in country
306  * information found with the country code.
307  */
308 static void
309 brcms_c_set_country(struct brcms_cm_info *wlc_cm,
310                     const struct brcms_regd *regd)
311 {
312         struct brcms_c_info *wlc = wlc_cm->wlc;
313
314         if ((wlc->pub->_n_enab & SUPPORT_11N) !=
315             wlc->protection->nmode_user)
316                 brcms_c_set_nmode(wlc);
317
318         brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
319         brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
320
321         brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false);
322
323         return;
324 }
325
326 struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc)
327 {
328         struct brcms_cm_info *wlc_cm;
329         struct brcms_pub *pub = wlc->pub;
330         struct ssb_sprom *sprom = &wlc->hw->d11core->bus->sprom;
331         const char *ccode = sprom->alpha2;
332         int ccode_len = sizeof(sprom->alpha2);
333
334         wlc_cm = kzalloc(sizeof(struct brcms_cm_info), GFP_ATOMIC);
335         if (wlc_cm == NULL)
336                 return NULL;
337         wlc_cm->pub = pub;
338         wlc_cm->wlc = wlc;
339         wlc->cmi = wlc_cm;
340
341         /* store the country code for passing up as a regulatory hint */
342         wlc_cm->world_regd = brcms_world_regd(ccode, ccode_len);
343         if (brcms_c_country_valid(ccode))
344                 strncpy(wlc->pub->srom_ccode, ccode, ccode_len);
345
346         /*
347          * If no custom world domain is found in the SROM, use the
348          * default "X2" domain.
349          */
350         if (!wlc_cm->world_regd) {
351                 wlc_cm->world_regd = brcms_default_world_regd();
352                 ccode = wlc_cm->world_regd->regdomain->alpha2;
353                 ccode_len = BRCM_CNTRY_BUF_SZ - 1;
354         }
355
356         /* save default country for exiting 11d regulatory mode */
357         strncpy(wlc->country_default, ccode, ccode_len);
358
359         /* initialize autocountry_default to driver default */
360         strncpy(wlc->autocountry_default, ccode, ccode_len);
361
362         brcms_c_set_country(wlc_cm, wlc_cm->world_regd);
363
364         return wlc_cm;
365 }
366
367 void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm)
368 {
369         kfree(wlc_cm);
370 }
371
372 void
373 brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec,
374                          u8 local_constraint_qdbm)
375 {
376         struct brcms_c_info *wlc = wlc_cm->wlc;
377         struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.chandef.chan;
378         struct txpwr_limits txpwr;
379
380         brcms_c_channel_reg_limits(wlc_cm, chanspec, &txpwr);
381
382         brcms_c_channel_min_txpower_limits_with_local_constraint(
383                 wlc_cm, &txpwr, local_constraint_qdbm
384         );
385
386         /* set or restore gmode as required by regulatory */
387         if (ch->flags & IEEE80211_CHAN_NO_OFDM)
388                 brcms_c_set_gmode(wlc, GMODE_LEGACY_B, false);
389         else
390                 brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false);
391
392         brcms_b_set_chanspec(wlc->hw, chanspec,
393                               !!(ch->flags & IEEE80211_CHAN_NO_IR),
394                               &txpwr);
395 }
396
397 void
398 brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,
399                        struct txpwr_limits *txpwr)
400 {
401         struct brcms_c_info *wlc = wlc_cm->wlc;
402         struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.chandef.chan;
403         uint i;
404         uint chan;
405         int maxpwr;
406         int delta;
407         const struct country_info *country;
408         struct brcms_band *band;
409         int conducted_max = BRCMS_TXPWR_MAX;
410         const struct locale_mimo_info *li_mimo;
411         int maxpwr20, maxpwr40;
412         int maxpwr_idx;
413         uint j;
414
415         memset(txpwr, 0, sizeof(struct txpwr_limits));
416
417         if (WARN_ON(!ch))
418                 return;
419
420         country = &wlc_cm->world_regd->country;
421
422         chan = CHSPEC_CHANNEL(chanspec);
423         band = wlc->bandstate[chspec_bandunit(chanspec)];
424         li_mimo = (band->bandtype == BRCM_BAND_5G) ?
425             brcms_c_get_mimo_5g(country->locale_mimo_5G) :
426             brcms_c_get_mimo_2g(country->locale_mimo_2G);
427
428         delta = band->antgain;
429
430         if (band->bandtype == BRCM_BAND_2G)
431                 conducted_max = QDB(22);
432
433         maxpwr = QDB(ch->max_power) - delta;
434         maxpwr = max(maxpwr, 0);
435         maxpwr = min(maxpwr, conducted_max);
436
437         /* CCK txpwr limits for 2.4G band */
438         if (band->bandtype == BRCM_BAND_2G) {
439                 for (i = 0; i < BRCMS_NUM_RATES_CCK; i++)
440                         txpwr->cck[i] = (u8) maxpwr;
441         }
442
443         for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) {
444                 txpwr->ofdm[i] = (u8) maxpwr;
445
446                 /*
447                  * OFDM 40 MHz SISO has the same power as the corresponding
448                  * MCS0-7 rate unless overriden by the locale specific code.
449                  * We set this value to 0 as a flag (presumably 0 dBm isn't
450                  * a possibility) and then copy the MCS0-7 value to the 40 MHz
451                  * value if it wasn't explicitly set.
452                  */
453                 txpwr->ofdm_40_siso[i] = 0;
454
455                 txpwr->ofdm_cdd[i] = (u8) maxpwr;
456
457                 txpwr->ofdm_40_cdd[i] = 0;
458         }
459
460         delta = 0;
461         if (band->antgain > QDB(6))
462                 delta = band->antgain - QDB(6); /* Excess over 6 dB */
463
464         if (band->bandtype == BRCM_BAND_2G)
465                 maxpwr_idx = (chan - 1);
466         else
467                 maxpwr_idx = CHANNEL_POWER_IDX_5G(chan);
468
469         maxpwr20 = li_mimo->maxpwr20[maxpwr_idx];
470         maxpwr40 = li_mimo->maxpwr40[maxpwr_idx];
471
472         maxpwr20 = maxpwr20 - delta;
473         maxpwr20 = max(maxpwr20, 0);
474         maxpwr40 = maxpwr40 - delta;
475         maxpwr40 = max(maxpwr40, 0);
476
477         /* Fill in the MCS 0-7 (SISO) rates */
478         for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
479
480                 /*
481                  * 20 MHz has the same power as the corresponding OFDM rate
482                  * unless overriden by the locale specific code.
483                  */
484                 txpwr->mcs_20_siso[i] = txpwr->ofdm[i];
485                 txpwr->mcs_40_siso[i] = 0;
486         }
487
488         /* Fill in the MCS 0-7 CDD rates */
489         for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
490                 txpwr->mcs_20_cdd[i] = (u8) maxpwr20;
491                 txpwr->mcs_40_cdd[i] = (u8) maxpwr40;
492         }
493
494         /*
495          * These locales have SISO expressed in the
496          * table and override CDD later
497          */
498         if (li_mimo == &locale_bn) {
499                 if (li_mimo == &locale_bn) {
500                         maxpwr20 = QDB(16);
501                         maxpwr40 = 0;
502
503                         if (chan >= 3 && chan <= 11)
504                                 maxpwr40 = QDB(16);
505                 }
506
507                 for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
508                         txpwr->mcs_20_siso[i] = (u8) maxpwr20;
509                         txpwr->mcs_40_siso[i] = (u8) maxpwr40;
510                 }
511         }
512
513         /* Fill in the MCS 0-7 STBC rates */
514         for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
515                 txpwr->mcs_20_stbc[i] = 0;
516                 txpwr->mcs_40_stbc[i] = 0;
517         }
518
519         /* Fill in the MCS 8-15 SDM rates */
520         for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++) {
521                 txpwr->mcs_20_mimo[i] = (u8) maxpwr20;
522                 txpwr->mcs_40_mimo[i] = (u8) maxpwr40;
523         }
524
525         /* Fill in MCS32 */
526         txpwr->mcs32 = (u8) maxpwr40;
527
528         for (i = 0, j = 0; i < BRCMS_NUM_RATES_OFDM; i++, j++) {
529                 if (txpwr->ofdm_40_cdd[i] == 0)
530                         txpwr->ofdm_40_cdd[i] = txpwr->mcs_40_cdd[j];
531                 if (i == 0) {
532                         i = i + 1;
533                         if (txpwr->ofdm_40_cdd[i] == 0)
534                                 txpwr->ofdm_40_cdd[i] = txpwr->mcs_40_cdd[j];
535                 }
536         }
537
538         /*
539          * Copy the 40 MHZ MCS 0-7 CDD value to the 40 MHZ MCS 0-7 SISO
540          * value if it wasn't provided explicitly.
541          */
542         for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
543                 if (txpwr->mcs_40_siso[i] == 0)
544                         txpwr->mcs_40_siso[i] = txpwr->mcs_40_cdd[i];
545         }
546
547         for (i = 0, j = 0; i < BRCMS_NUM_RATES_OFDM; i++, j++) {
548                 if (txpwr->ofdm_40_siso[i] == 0)
549                         txpwr->ofdm_40_siso[i] = txpwr->mcs_40_siso[j];
550                 if (i == 0) {
551                         i = i + 1;
552                         if (txpwr->ofdm_40_siso[i] == 0)
553                                 txpwr->ofdm_40_siso[i] = txpwr->mcs_40_siso[j];
554                 }
555         }
556
557         /*
558          * Copy the 20 and 40 MHz MCS0-7 CDD values to the corresponding
559          * STBC values if they weren't provided explicitly.
560          */
561         for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
562                 if (txpwr->mcs_20_stbc[i] == 0)
563                         txpwr->mcs_20_stbc[i] = txpwr->mcs_20_cdd[i];
564
565                 if (txpwr->mcs_40_stbc[i] == 0)
566                         txpwr->mcs_40_stbc[i] = txpwr->mcs_40_cdd[i];
567         }
568
569         return;
570 }
571
572 /*
573  * Verify the chanspec is using a legal set of parameters, i.e. that the
574  * chanspec specified a band, bw, ctl_sb and channel and that the
575  * combination could be legal given any set of circumstances.
576  * RETURNS: true is the chanspec is malformed, false if it looks good.
577  */
578 static bool brcms_c_chspec_malformed(u16 chanspec)
579 {
580         /* must be 2G or 5G band */
581         if (!CHSPEC_IS5G(chanspec) && !CHSPEC_IS2G(chanspec))
582                 return true;
583         /* must be 20 or 40 bandwidth */
584         if (!CHSPEC_IS40(chanspec) && !CHSPEC_IS20(chanspec))
585                 return true;
586
587         /* 20MHZ b/w must have no ctl sb, 40 must have a ctl sb */
588         if (CHSPEC_IS20(chanspec)) {
589                 if (!CHSPEC_SB_NONE(chanspec))
590                         return true;
591         } else if (!CHSPEC_SB_UPPER(chanspec) && !CHSPEC_SB_LOWER(chanspec)) {
592                 return true;
593         }
594
595         return false;
596 }
597
598 /*
599  * Validate the chanspec for this locale, for 40MHZ we need to also
600  * check that the sidebands are valid 20MZH channels in this locale
601  * and they are also a legal HT combination
602  */
603 static bool
604 brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec)
605 {
606         struct brcms_c_info *wlc = wlc_cm->wlc;
607         u8 channel = CHSPEC_CHANNEL(chspec);
608
609         /* check the chanspec */
610         if (brcms_c_chspec_malformed(chspec)) {
611                 brcms_err(wlc->hw->d11core, "wl%d: malformed chanspec 0x%x\n",
612                           wlc->pub->unit, chspec);
613                 return false;
614         }
615
616         if (CHANNEL_BANDUNIT(wlc_cm->wlc, channel) !=
617             chspec_bandunit(chspec))
618                 return false;
619
620         return true;
621 }
622
623 bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, u16 chspec)
624 {
625         return brcms_c_valid_chanspec_ext(wlc_cm, chspec);
626 }
627
628 static bool brcms_is_radar_freq(u16 center_freq)
629 {
630         return center_freq >= 5260 && center_freq <= 5700;
631 }
632
633 static void brcms_reg_apply_radar_flags(struct wiphy *wiphy)
634 {
635         struct ieee80211_supported_band *sband;
636         struct ieee80211_channel *ch;
637         int i;
638
639         sband = wiphy->bands[NL80211_BAND_5GHZ];
640         if (!sband)
641                 return;
642
643         for (i = 0; i < sband->n_channels; i++) {
644                 ch = &sband->channels[i];
645
646                 if (!brcms_is_radar_freq(ch->center_freq))
647                         continue;
648
649                 /*
650                  * All channels in this range should be passive and have
651                  * DFS enabled.
652                  */
653                 if (!(ch->flags & IEEE80211_CHAN_DISABLED))
654                         ch->flags |= IEEE80211_CHAN_RADAR |
655                                      IEEE80211_CHAN_NO_IR |
656                                      IEEE80211_CHAN_NO_IR;
657         }
658 }
659
660 static void
661 brcms_reg_apply_beaconing_flags(struct wiphy *wiphy,
662                                 enum nl80211_reg_initiator initiator)
663 {
664         struct ieee80211_supported_band *sband;
665         struct ieee80211_channel *ch;
666         const struct ieee80211_reg_rule *rule;
667         int band, i;
668
669         for (band = 0; band < NUM_NL80211_BANDS; band++) {
670                 sband = wiphy->bands[band];
671                 if (!sband)
672                         continue;
673
674                 for (i = 0; i < sband->n_channels; i++) {
675                         ch = &sband->channels[i];
676
677                         if (ch->flags &
678                             (IEEE80211_CHAN_DISABLED | IEEE80211_CHAN_RADAR))
679                                 continue;
680
681                         if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
682                                 rule = freq_reg_info(wiphy,
683                                                      MHZ_TO_KHZ(ch->center_freq));
684                                 if (IS_ERR(rule))
685                                         continue;
686
687                                 if (!(rule->flags & NL80211_RRF_NO_IR))
688                                         ch->flags &= ~IEEE80211_CHAN_NO_IR;
689                         } else if (ch->beacon_found) {
690                                 ch->flags &= ~IEEE80211_CHAN_NO_IR;
691                         }
692                 }
693         }
694 }
695
696 static void brcms_reg_notifier(struct wiphy *wiphy,
697                                struct regulatory_request *request)
698 {
699         struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
700         struct brcms_info *wl = hw->priv;
701         struct brcms_c_info *wlc = wl->wlc;
702         struct ieee80211_supported_band *sband;
703         struct ieee80211_channel *ch;
704         int band, i;
705         bool ch_found = false;
706
707         brcms_reg_apply_radar_flags(wiphy);
708
709         if (request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)
710                 brcms_reg_apply_beaconing_flags(wiphy, request->initiator);
711
712         /* Disable radio if all channels disallowed by regulatory */
713         for (band = 0; !ch_found && band < NUM_NL80211_BANDS; band++) {
714                 sband = wiphy->bands[band];
715                 if (!sband)
716                         continue;
717
718                 for (i = 0; !ch_found && i < sband->n_channels; i++) {
719                         ch = &sband->channels[i];
720
721                         if (!(ch->flags & IEEE80211_CHAN_DISABLED))
722                                 ch_found = true;
723                 }
724         }
725
726         if (ch_found) {
727                 mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
728         } else {
729                 mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
730                 brcms_err(wlc->hw->d11core,
731                           "wl%d: %s: no valid channel for \"%s\"\n",
732                           wlc->pub->unit, __func__, request->alpha2);
733         }
734
735         if (wlc->pub->_nbands > 1 || wlc->band->bandtype == BRCM_BAND_2G)
736                 wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi,
737                                         brcms_c_japan_ccode(request->alpha2));
738 }
739
740 void brcms_c_regd_init(struct brcms_c_info *wlc)
741 {
742         struct wiphy *wiphy = wlc->wiphy;
743         const struct brcms_regd *regd = wlc->cmi->world_regd;
744         struct ieee80211_supported_band *sband;
745         struct ieee80211_channel *ch;
746         struct brcms_chanvec sup_chan;
747         struct brcms_band *band;
748         int band_idx, i;
749
750         /* Disable any channels not supported by the phy */
751         for (band_idx = 0; band_idx < wlc->pub->_nbands; band_idx++) {
752                 band = wlc->bandstate[band_idx];
753
754                 wlc_phy_chanspec_band_validch(band->pi, band->bandtype,
755                                               &sup_chan);
756
757                 if (band_idx == BAND_2G_INDEX)
758                         sband = wiphy->bands[NL80211_BAND_2GHZ];
759                 else
760                         sband = wiphy->bands[NL80211_BAND_5GHZ];
761
762                 for (i = 0; i < sband->n_channels; i++) {
763                         ch = &sband->channels[i];
764                         if (!isset(sup_chan.vec, ch->hw_value))
765                                 ch->flags |= IEEE80211_CHAN_DISABLED;
766                 }
767         }
768
769         wlc->wiphy->reg_notifier = brcms_reg_notifier;
770         wlc->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |
771                                         REGULATORY_STRICT_REG;
772         wiphy_apply_custom_regulatory(wlc->wiphy, regd->regdomain);
773         brcms_reg_apply_beaconing_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER);
774 }