aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211/brcmsmac/channel.c
diff options
context:
space:
mode:
authorSeth Forshee <seth.forshee@canonical.com>2012-06-16 08:47:56 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-06-20 15:14:40 -0400
commitedc7651f3a4ffa7fca37d92401562694121512ad (patch)
tree02942a1b03376e63f04395667681dad3b4d9d517 /drivers/net/wireless/brcm80211/brcmsmac/channel.c
parent853346d8b60738467581d1cd9ccb678aeb086121 (diff)
brcm80211: smac: use current regulatory domain when checking whether OFDM is allowed
The brcmsmac internal regulatory data is being used to determine whether OFDM should be allowed, and this is only done once during initialization. To be effective this needs to be checked against mac80211's regulatory rules for the current channel. Reviewed-by: Arend Van Spriel <arend@broadcom.com> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Signed-off-by: Seth Forshee <seth.forshee@canonical.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmsmac/channel.c')
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/channel.c132
1 files changed, 14 insertions, 118 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
index 04e6a6ec77ff..d3c726021c35 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
@@ -30,13 +30,9 @@
30/* QDB() macro takes a dB value and converts to a quarter dB value */ 30/* QDB() macro takes a dB value and converts to a quarter dB value */
31#define QDB(n) ((n) * BRCMS_TXPWR_DB_FACTOR) 31#define QDB(n) ((n) * BRCMS_TXPWR_DB_FACTOR)
32 32
33#define LOCALE_2G_IDX_i 0
34#define LOCALE_5G_IDX_11 0
35#define LOCALE_MIMO_IDX_bn 0 33#define LOCALE_MIMO_IDX_bn 0
36#define LOCALE_MIMO_IDX_11n 0 34#define LOCALE_MIMO_IDX_11n 0
37 35
38/* max of BAND_5G_PWR_LVLS and 6 for 2.4 GHz */
39#define BRCMS_MAXPWR_TBL_SIZE 6
40/* max of BAND_5G_PWR_LVLS and 14 for 2.4 GHz */ 36/* max of BAND_5G_PWR_LVLS and 14 for 2.4 GHz */
41#define BRCMS_MAXPWR_MIMO_TBL_SIZE 14 37#define BRCMS_MAXPWR_MIMO_TBL_SIZE 14
42 38
@@ -51,12 +47,8 @@
51 47
52#define LC(id) LOCALE_MIMO_IDX_ ## id 48#define LC(id) LOCALE_MIMO_IDX_ ## id
53 49
54#define LC_2G(id) LOCALE_2G_IDX_ ## id 50#define LOCALES(mimo2, mimo5) \
55 51 {LC(mimo2), LC(mimo5)}
56#define LC_5G(id) LOCALE_5G_IDX_ ## id
57
58#define LOCALES(band2, band5, mimo2, mimo5) \
59 {LC_2G(band2), LC_5G(band5), LC(mimo2), LC(mimo5)}
60 52
61/* macro to get 5 GHz channel group index for tx power */ 53/* macro to get 5 GHz channel group index for tx power */
62#define CHANNEL_POWER_IDX_5G(c) (((c) < 52) ? 0 : \ 54#define CHANNEL_POWER_IDX_5G(c) (((c) < 52) ? 0 : \
@@ -97,11 +89,6 @@ static const struct ieee80211_regdomain brcms_regdom_x2 = {
97 } 89 }
98}; 90};
99 91
100struct brcms_cm_band {
101 /* struct locale_info flags */
102 u8 locale_flags;
103};
104
105 /* locale per-channel tx power limits for MIMO frames 92 /* locale per-channel tx power limits for MIMO frames
106 * maxpwr arrays are index by channel for 2.4 GHz limits, and 93 * maxpwr arrays are index by channel for 2.4 GHz limits, and
107 * by sub-band for 5 GHz limits using CHANNEL_POWER_IDX_5G(channel) 94 * by sub-band for 5 GHz limits using CHANNEL_POWER_IDX_5G(channel)
@@ -111,13 +98,10 @@ struct locale_mimo_info {
111 s8 maxpwr20[BRCMS_MAXPWR_MIMO_TBL_SIZE]; 98 s8 maxpwr20[BRCMS_MAXPWR_MIMO_TBL_SIZE];
112 /* tx 40 MHz power limits, qdBm units */ 99 /* tx 40 MHz power limits, qdBm units */
113 s8 maxpwr40[BRCMS_MAXPWR_MIMO_TBL_SIZE]; 100 s8 maxpwr40[BRCMS_MAXPWR_MIMO_TBL_SIZE];
114 u8 flags;
115}; 101};
116 102
117/* Country names and abbreviations with locale defined from ISO 3166 */ 103/* Country names and abbreviations with locale defined from ISO 3166 */
118struct country_info { 104struct country_info {
119 const u8 locale_2G; /* 2.4G band locale */
120 const u8 locale_5G; /* 5G band locale */
121 const u8 locale_mimo_2G; /* 2.4G mimo info */ 105 const u8 locale_mimo_2G; /* 2.4G mimo info */
122 const u8 locale_mimo_5G; /* 5G mimo info */ 106 const u8 locale_mimo_5G; /* 5G mimo info */
123}; 107};
@@ -131,35 +115,6 @@ struct brcms_cm_info {
131 struct brcms_pub *pub; 115 struct brcms_pub *pub;
132 struct brcms_c_info *wlc; 116 struct brcms_c_info *wlc;
133 const struct brcms_regd *world_regd; 117 const struct brcms_regd *world_regd;
134 /* per-band state (one per phy/radio) */
135 struct brcms_cm_band bandstate[MAXBANDS];
136};
137
138/* locale channel and power info. */
139struct locale_info {
140 u8 flags;
141};
142
143/*
144 * Locale Definitions - 2.4 GHz
145 */
146static const struct locale_info locale_i = { /* locale i. channel 1 - 13 */
147 BRCMS_EIRP
148};
149
150/*
151 * Locale Definitions - 5 GHz
152 */
153static const struct locale_info locale_11 = {
154 BRCMS_EIRP | BRCMS_DFS_EU
155};
156
157static const struct locale_info *g_locale_2g_table[] = {
158 &locale_i
159};
160
161static const struct locale_info *g_locale_5g_table[] = {
162 &locale_11
163}; 118};
164 119
165/* 120/*
@@ -172,7 +127,6 @@ static const struct locale_mimo_info locale_bn = {
172 {0, 0, QDB(13), QDB(13), QDB(13), 127 {0, 0, QDB(13), QDB(13), QDB(13),
173 QDB(13), QDB(13), QDB(13), QDB(13), QDB(13), 128 QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
174 QDB(13), 0, 0}, 129 QDB(13), 0, 0},
175 0
176}; 130};
177 131
178static const struct locale_mimo_info *g_mimo_2g_table[] = { 132static const struct locale_mimo_info *g_mimo_2g_table[] = {
@@ -185,7 +139,6 @@ static const struct locale_mimo_info *g_mimo_2g_table[] = {
185static const struct locale_mimo_info locale_11n = { 139static const struct locale_mimo_info locale_11n = {
186 { /* 12.5 dBm */ 50, 50, 50, QDB(15), QDB(15)}, 140 { /* 12.5 dBm */ 50, 50, 50, QDB(15), QDB(15)},
187 {QDB(14), QDB(15), QDB(15), QDB(15), QDB(15)}, 141 {QDB(14), QDB(15), QDB(15), QDB(15), QDB(15)},
188 0
189}; 142};
190 143
191static const struct locale_mimo_info *g_mimo_5g_table[] = { 144static const struct locale_mimo_info *g_mimo_5g_table[] = {
@@ -195,27 +148,11 @@ static const struct locale_mimo_info *g_mimo_5g_table[] = {
195static const struct brcms_regd cntry_locales[] = { 148static const struct brcms_regd cntry_locales[] = {
196 /* Worldwide RoW 2, must always be at index 0 */ 149 /* Worldwide RoW 2, must always be at index 0 */
197 { 150 {
198 .country = LOCALES(i, 11, bn, 11n), 151 .country = LOCALES(bn, 11n),
199 .regdomain = &brcms_regdom_x2, 152 .regdomain = &brcms_regdom_x2,
200 }, 153 },
201}; 154};
202 155
203static const struct locale_info *brcms_c_get_locale_2g(u8 locale_idx)
204{
205 if (locale_idx >= ARRAY_SIZE(g_locale_2g_table))
206 return NULL; /* error condition */
207
208 return g_locale_2g_table[locale_idx];
209}
210
211static const struct locale_info *brcms_c_get_locale_5g(u8 locale_idx)
212{
213 if (locale_idx >= ARRAY_SIZE(g_locale_5g_table))
214 return NULL; /* error condition */
215
216 return g_locale_5g_table[locale_idx];
217}
218
219static const struct locale_mimo_info *brcms_c_get_mimo_2g(u8 locale_idx) 156static const struct locale_mimo_info *brcms_c_get_mimo_2g(u8 locale_idx)
220{ 157{
221 if (locale_idx >= ARRAY_SIZE(g_mimo_2g_table)) 158 if (locale_idx >= ARRAY_SIZE(g_mimo_2g_table))
@@ -368,36 +305,6 @@ brcms_c_channel_min_txpower_limits_with_local_constraint(
368 305
369} 306}
370 307
371static int
372brcms_c_channels_init(struct brcms_cm_info *wlc_cm,
373 const struct country_info *country)
374{
375 struct brcms_c_info *wlc = wlc_cm->wlc;
376 uint i;
377 struct brcms_band *band;
378 const struct locale_info *li;
379 const struct locale_mimo_info *li_mimo;
380
381 band = wlc->band;
382 for (i = 0; i < wlc->pub->_nbands;
383 i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) {
384
385 li = (band->bandtype == BRCM_BAND_5G) ?
386 brcms_c_get_locale_5g(country->locale_5G) :
387 brcms_c_get_locale_2g(country->locale_2G);
388 wlc_cm->bandstate[band->bandunit].locale_flags = li->flags;
389 li_mimo = (band->bandtype == BRCM_BAND_5G) ?
390 brcms_c_get_mimo_5g(country->locale_mimo_5G) :
391 brcms_c_get_mimo_2g(country->locale_mimo_2G);
392
393 /* merge the mimo non-mimo locale flags */
394 wlc_cm->bandstate[band->bandunit].locale_flags |=
395 li_mimo->flags;
396 }
397
398 return 0;
399}
400
401/* 308/*
402 * set the driver's current country and regulatory information 309 * set the driver's current country and regulatory information
403 * using a country code as the source. Look up built in country 310 * using a country code as the source. Look up built in country
@@ -407,8 +314,6 @@ static void
407brcms_c_set_country(struct brcms_cm_info *wlc_cm, 314brcms_c_set_country(struct brcms_cm_info *wlc_cm,
408 const struct brcms_regd *regd) 315 const struct brcms_regd *regd)
409{ 316{
410 const struct country_info *country = &regd->country;
411 const struct locale_info *locale;
412 struct brcms_c_info *wlc = wlc_cm->wlc; 317 struct brcms_c_info *wlc = wlc_cm->wlc;
413 318
414 if ((wlc->pub->_n_enab & SUPPORT_11N) != 319 if ((wlc->pub->_n_enab & SUPPORT_11N) !=
@@ -417,14 +322,8 @@ brcms_c_set_country(struct brcms_cm_info *wlc_cm,
417 322
418 brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]); 323 brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
419 brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]); 324 brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
420 /* set or restore gmode as required by regulatory */
421 locale = brcms_c_get_locale_2g(country->locale_2G);
422 if (locale && (locale->flags & BRCMS_NO_OFDM))
423 brcms_c_set_gmode(wlc, GMODE_LEGACY_B, false);
424 else
425 brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false);
426 325
427 brcms_c_channels_init(wlc_cm, country); 326 brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false);
428 327
429 return; 328 return;
430} 329}
@@ -477,20 +376,15 @@ void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm)
477 kfree(wlc_cm); 376 kfree(wlc_cm);
478} 377}
479 378
480u8
481brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm,
482 uint bandunit)
483{
484 return wlc_cm->bandstate[bandunit].locale_flags;
485}
486
487void 379void
488brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec, 380brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec,
489 u8 local_constraint_qdbm) 381 u8 local_constraint_qdbm)
490{ 382{
491 struct brcms_c_info *wlc = wlc_cm->wlc; 383 struct brcms_c_info *wlc = wlc_cm->wlc;
492 struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.channel; 384 struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.channel;
385 const struct ieee80211_reg_rule *reg_rule;
493 struct txpwr_limits txpwr; 386 struct txpwr_limits txpwr;
387 int ret;
494 388
495 brcms_c_channel_reg_limits(wlc_cm, chanspec, &txpwr); 389 brcms_c_channel_reg_limits(wlc_cm, chanspec, &txpwr);
496 390
@@ -498,6 +392,13 @@ brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec,
498 wlc_cm, &txpwr, local_constraint_qdbm 392 wlc_cm, &txpwr, local_constraint_qdbm
499 ); 393 );
500 394
395 /* set or restore gmode as required by regulatory */
396 ret = freq_reg_info(wlc->wiphy, ch->center_freq, 0, &reg_rule);
397 if (!ret && (reg_rule->flags & NL80211_RRF_NO_OFDM))
398 brcms_c_set_gmode(wlc, GMODE_LEGACY_B, false);
399 else
400 brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false);
401
501 brcms_b_set_chanspec(wlc->hw, chanspec, 402 brcms_b_set_chanspec(wlc->hw, chanspec,
502 !!(ch->flags & IEEE80211_CHAN_PASSIVE_SCAN), 403 !!(ch->flags & IEEE80211_CHAN_PASSIVE_SCAN),
503 &txpwr); 404 &txpwr);
@@ -515,7 +416,6 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,
515 int delta; 416 int delta;
516 const struct country_info *country; 417 const struct country_info *country;
517 struct brcms_band *band; 418 struct brcms_band *band;
518 const struct locale_info *li;
519 int conducted_max = BRCMS_TXPWR_MAX; 419 int conducted_max = BRCMS_TXPWR_MAX;
520 const struct locale_mimo_info *li_mimo; 420 const struct locale_mimo_info *li_mimo;
521 int maxpwr20, maxpwr40; 421 int maxpwr20, maxpwr40;
@@ -531,17 +431,13 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,
531 431
532 chan = CHSPEC_CHANNEL(chanspec); 432 chan = CHSPEC_CHANNEL(chanspec);
533 band = wlc->bandstate[chspec_bandunit(chanspec)]; 433 band = wlc->bandstate[chspec_bandunit(chanspec)];
534 li = (band->bandtype == BRCM_BAND_5G) ?
535 brcms_c_get_locale_5g(country->locale_5G) :
536 brcms_c_get_locale_2g(country->locale_2G);
537
538 li_mimo = (band->bandtype == BRCM_BAND_5G) ? 434 li_mimo = (band->bandtype == BRCM_BAND_5G) ?
539 brcms_c_get_mimo_5g(country->locale_mimo_5G) : 435 brcms_c_get_mimo_5g(country->locale_mimo_5G) :
540 brcms_c_get_mimo_2g(country->locale_mimo_2G); 436 brcms_c_get_mimo_2g(country->locale_mimo_2G);
541 437
542 delta = band->antgain; 438 delta = band->antgain;
543 439
544 if (li == &locale_i) 440 if (band->bandtype == BRCM_BAND_2G)
545 conducted_max = QDB(22); 441 conducted_max = QDB(22);
546 442
547 maxpwr = QDB(ch->max_power) - delta; 443 maxpwr = QDB(ch->max_power) - delta;