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