aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211/brcmsmac/channel.c
diff options
context:
space:
mode:
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;