diff options
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmsmac/channel.c')
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmsmac/channel.c | 132 |
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 | ||
100 | struct 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 */ |
118 | struct country_info { | 104 | struct 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. */ | ||
139 | struct locale_info { | ||
140 | u8 flags; | ||
141 | }; | ||
142 | |||
143 | /* | ||
144 | * Locale Definitions - 2.4 GHz | ||
145 | */ | ||
146 | static const struct locale_info locale_i = { /* locale i. channel 1 - 13 */ | ||
147 | BRCMS_EIRP | ||
148 | }; | ||
149 | |||
150 | /* | ||
151 | * Locale Definitions - 5 GHz | ||
152 | */ | ||
153 | static const struct locale_info locale_11 = { | ||
154 | BRCMS_EIRP | BRCMS_DFS_EU | ||
155 | }; | ||
156 | |||
157 | static const struct locale_info *g_locale_2g_table[] = { | ||
158 | &locale_i | ||
159 | }; | ||
160 | |||
161 | static 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 | ||
178 | static const struct locale_mimo_info *g_mimo_2g_table[] = { | 132 | static const struct locale_mimo_info *g_mimo_2g_table[] = { |
@@ -185,7 +139,6 @@ static const struct locale_mimo_info *g_mimo_2g_table[] = { | |||
185 | static const struct locale_mimo_info locale_11n = { | 139 | static 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 | ||
191 | static const struct locale_mimo_info *g_mimo_5g_table[] = { | 144 | static const struct locale_mimo_info *g_mimo_5g_table[] = { |
@@ -195,27 +148,11 @@ static const struct locale_mimo_info *g_mimo_5g_table[] = { | |||
195 | static const struct brcms_regd cntry_locales[] = { | 148 | static 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 | ||
203 | static 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 | |||
211 | static 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 | |||
219 | static const struct locale_mimo_info *brcms_c_get_mimo_2g(u8 locale_idx) | 156 | static 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 | ||
371 | static int | ||
372 | brcms_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 | |||
407 | brcms_c_set_country(struct brcms_cm_info *wlc_cm, | 314 | brcms_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 = ®d->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 | ||
480 | u8 | ||
481 | brcms_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 | |||
487 | void | 379 | void |
488 | brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec, | 380 | brcms_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, ®_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; |