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