diff options
author | John W. Linville <linville@tuxdriver.com> | 2013-11-04 14:51:28 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-11-04 14:51:28 -0500 |
commit | 87bc0728d462ae37841a550542829aa65a97e7c2 (patch) | |
tree | 266afb90f501b814c0a79f10a7afd86a6a33d631 /net/mac80211 | |
parent | f421436a591d34fa5279b54a96ac07d70250cc8d (diff) | |
parent | 01925efdf7e03b4b803b5c9f985163d687f7f017 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Conflicts:
drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/ieee80211_i.h | 1 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 95 | ||||
-rw-r--r-- | net/mac80211/rate.c | 15 |
3 files changed, 99 insertions, 12 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index e73cd0637f3b..fe48b093d4dc 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -334,6 +334,7 @@ enum ieee80211_sta_flags { | |||
334 | IEEE80211_STA_DISABLE_VHT = BIT(11), | 334 | IEEE80211_STA_DISABLE_VHT = BIT(11), |
335 | IEEE80211_STA_DISABLE_80P80MHZ = BIT(12), | 335 | IEEE80211_STA_DISABLE_80P80MHZ = BIT(12), |
336 | IEEE80211_STA_DISABLE_160MHZ = BIT(13), | 336 | IEEE80211_STA_DISABLE_160MHZ = BIT(13), |
337 | IEEE80211_STA_DISABLE_WMM = BIT(14), | ||
337 | }; | 338 | }; |
338 | 339 | ||
339 | struct ieee80211_mgd_auth_data { | 340 | struct ieee80211_mgd_auth_data { |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 91cc8281e266..d7bdc4b97dde 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -2527,7 +2527,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
2527 | */ | 2527 | */ |
2528 | ifmgd->wmm_last_param_set = -1; | 2528 | ifmgd->wmm_last_param_set = -1; |
2529 | 2529 | ||
2530 | if (elems.wmm_param) | 2530 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_WMM) && elems.wmm_param) |
2531 | ieee80211_sta_wmm_params(local, sdata, elems.wmm_param, | 2531 | ieee80211_sta_wmm_params(local, sdata, elems.wmm_param, |
2532 | elems.wmm_param_len); | 2532 | elems.wmm_param_len); |
2533 | else | 2533 | else |
@@ -2955,7 +2955,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2955 | ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, | 2955 | ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, |
2956 | &elems, true); | 2956 | &elems, true); |
2957 | 2957 | ||
2958 | if (ieee80211_sta_wmm_params(local, sdata, elems.wmm_param, | 2958 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_WMM) && |
2959 | ieee80211_sta_wmm_params(local, sdata, elems.wmm_param, | ||
2959 | elems.wmm_param_len)) | 2960 | elems.wmm_param_len)) |
2960 | changed |= BSS_CHANGED_QOS; | 2961 | changed |= BSS_CHANGED_QOS; |
2961 | 2962 | ||
@@ -3937,6 +3938,44 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | |||
3937 | return err; | 3938 | return err; |
3938 | } | 3939 | } |
3939 | 3940 | ||
3941 | static bool ieee80211_usable_wmm_params(struct ieee80211_sub_if_data *sdata, | ||
3942 | const u8 *wmm_param, int len) | ||
3943 | { | ||
3944 | const u8 *pos; | ||
3945 | size_t left; | ||
3946 | |||
3947 | if (len < 8) | ||
3948 | return false; | ||
3949 | |||
3950 | if (wmm_param[5] != 1 /* version */) | ||
3951 | return false; | ||
3952 | |||
3953 | pos = wmm_param + 8; | ||
3954 | left = len - 8; | ||
3955 | |||
3956 | for (; left >= 4; left -= 4, pos += 4) { | ||
3957 | u8 aifsn = pos[0] & 0x0f; | ||
3958 | u8 ecwmin = pos[1] & 0x0f; | ||
3959 | u8 ecwmax = (pos[1] & 0xf0) >> 4; | ||
3960 | int aci = (pos[0] >> 5) & 0x03; | ||
3961 | |||
3962 | if (aifsn < 2) { | ||
3963 | sdata_info(sdata, | ||
3964 | "AP has invalid WMM params (AIFSN=%d for ACI %d), disabling WMM\n", | ||
3965 | aifsn, aci); | ||
3966 | return false; | ||
3967 | } | ||
3968 | if (ecwmin > ecwmax) { | ||
3969 | sdata_info(sdata, | ||
3970 | "AP has invalid WMM params (ECWmin/max=%d/%d for ACI %d), disabling WMM\n", | ||
3971 | ecwmin, ecwmax, aci); | ||
3972 | return false; | ||
3973 | } | ||
3974 | } | ||
3975 | |||
3976 | return true; | ||
3977 | } | ||
3978 | |||
3940 | int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | 3979 | int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, |
3941 | struct cfg80211_assoc_request *req) | 3980 | struct cfg80211_assoc_request *req) |
3942 | { | 3981 | { |
@@ -3994,9 +4033,45 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3994 | } | 4033 | } |
3995 | 4034 | ||
3996 | /* prepare assoc data */ | 4035 | /* prepare assoc data */ |
3997 | 4036 | ||
3998 | ifmgd->beacon_crc_valid = false; | 4037 | ifmgd->beacon_crc_valid = false; |
3999 | 4038 | ||
4039 | assoc_data->wmm = bss->wmm_used && | ||
4040 | (local->hw.queues >= IEEE80211_NUM_ACS); | ||
4041 | if (assoc_data->wmm) { | ||
4042 | /* try to check validity of WMM params IE */ | ||
4043 | const struct cfg80211_bss_ies *ies; | ||
4044 | const u8 *wp, *start, *end; | ||
4045 | |||
4046 | rcu_read_lock(); | ||
4047 | ies = rcu_dereference(req->bss->ies); | ||
4048 | start = ies->data; | ||
4049 | end = start + ies->len; | ||
4050 | |||
4051 | while (true) { | ||
4052 | wp = cfg80211_find_vendor_ie( | ||
4053 | WLAN_OUI_MICROSOFT, | ||
4054 | WLAN_OUI_TYPE_MICROSOFT_WMM, | ||
4055 | start, end - start); | ||
4056 | if (!wp) | ||
4057 | break; | ||
4058 | start = wp + wp[1] + 2; | ||
4059 | /* if this IE is too short, try the next */ | ||
4060 | if (wp[1] <= 4) | ||
4061 | continue; | ||
4062 | /* if this IE is WMM params, we found what we wanted */ | ||
4063 | if (wp[6] == 1) | ||
4064 | break; | ||
4065 | } | ||
4066 | |||
4067 | if (!wp || !ieee80211_usable_wmm_params(sdata, wp + 2, | ||
4068 | wp[1] - 2)) { | ||
4069 | assoc_data->wmm = false; | ||
4070 | ifmgd->flags |= IEEE80211_STA_DISABLE_WMM; | ||
4071 | } | ||
4072 | rcu_read_unlock(); | ||
4073 | } | ||
4074 | |||
4000 | /* | 4075 | /* |
4001 | * IEEE802.11n does not allow TKIP/WEP as pairwise ciphers in HT mode. | 4076 | * IEEE802.11n does not allow TKIP/WEP as pairwise ciphers in HT mode. |
4002 | * We still associate in non-HT mode (11a/b/g) if any one of these | 4077 | * We still associate in non-HT mode (11a/b/g) if any one of these |
@@ -4026,18 +4101,22 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
4026 | /* Also disable HT if we don't support it or the AP doesn't use WMM */ | 4101 | /* Also disable HT if we don't support it or the AP doesn't use WMM */ |
4027 | sband = local->hw.wiphy->bands[req->bss->channel->band]; | 4102 | sband = local->hw.wiphy->bands[req->bss->channel->band]; |
4028 | if (!sband->ht_cap.ht_supported || | 4103 | if (!sband->ht_cap.ht_supported || |
4029 | local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) { | 4104 | local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used || |
4105 | ifmgd->flags & IEEE80211_STA_DISABLE_WMM) { | ||
4030 | ifmgd->flags |= IEEE80211_STA_DISABLE_HT; | 4106 | ifmgd->flags |= IEEE80211_STA_DISABLE_HT; |
4031 | if (!bss->wmm_used) | 4107 | if (!bss->wmm_used && |
4108 | !(ifmgd->flags & IEEE80211_STA_DISABLE_WMM)) | ||
4032 | netdev_info(sdata->dev, | 4109 | netdev_info(sdata->dev, |
4033 | "disabling HT as WMM/QoS is not supported by the AP\n"); | 4110 | "disabling HT as WMM/QoS is not supported by the AP\n"); |
4034 | } | 4111 | } |
4035 | 4112 | ||
4036 | /* disable VHT if we don't support it or the AP doesn't use WMM */ | 4113 | /* disable VHT if we don't support it or the AP doesn't use WMM */ |
4037 | if (!sband->vht_cap.vht_supported || | 4114 | if (!sband->vht_cap.vht_supported || |
4038 | local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) { | 4115 | local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used || |
4116 | ifmgd->flags & IEEE80211_STA_DISABLE_WMM) { | ||
4039 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; | 4117 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; |
4040 | if (!bss->wmm_used) | 4118 | if (!bss->wmm_used && |
4119 | !(ifmgd->flags & IEEE80211_STA_DISABLE_WMM)) | ||
4041 | netdev_info(sdata->dev, | 4120 | netdev_info(sdata->dev, |
4042 | "disabling VHT as WMM/QoS is not supported by the AP\n"); | 4121 | "disabling VHT as WMM/QoS is not supported by the AP\n"); |
4043 | } | 4122 | } |
@@ -4066,8 +4145,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
4066 | sdata->smps_mode = ifmgd->req_smps; | 4145 | sdata->smps_mode = ifmgd->req_smps; |
4067 | 4146 | ||
4068 | assoc_data->capability = req->bss->capability; | 4147 | assoc_data->capability = req->bss->capability; |
4069 | assoc_data->wmm = bss->wmm_used && | ||
4070 | (local->hw.queues >= IEEE80211_NUM_ACS); | ||
4071 | assoc_data->supp_rates = bss->supp_rates; | 4148 | assoc_data->supp_rates = bss->supp_rates; |
4072 | assoc_data->supp_rates_len = bss->supp_rates_len; | 4149 | assoc_data->supp_rates_len = bss->supp_rates_len; |
4073 | 4150 | ||
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index e126605cec66..22b223f13c9f 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -235,7 +235,8 @@ static void rc_send_low_basicrate(s8 *idx, u32 basic_rates, | |||
235 | static void __rate_control_send_low(struct ieee80211_hw *hw, | 235 | static void __rate_control_send_low(struct ieee80211_hw *hw, |
236 | struct ieee80211_supported_band *sband, | 236 | struct ieee80211_supported_band *sband, |
237 | struct ieee80211_sta *sta, | 237 | struct ieee80211_sta *sta, |
238 | struct ieee80211_tx_info *info) | 238 | struct ieee80211_tx_info *info, |
239 | u32 rate_mask) | ||
239 | { | 240 | { |
240 | int i; | 241 | int i; |
241 | u32 rate_flags = | 242 | u32 rate_flags = |
@@ -247,6 +248,12 @@ static void __rate_control_send_low(struct ieee80211_hw *hw, | |||
247 | 248 | ||
248 | info->control.rates[0].idx = 0; | 249 | info->control.rates[0].idx = 0; |
249 | for (i = 0; i < sband->n_bitrates; i++) { | 250 | for (i = 0; i < sband->n_bitrates; i++) { |
251 | if (!(rate_mask & BIT(i))) | ||
252 | continue; | ||
253 | |||
254 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) | ||
255 | continue; | ||
256 | |||
250 | if (!rate_supported(sta, sband->band, i)) | 257 | if (!rate_supported(sta, sband->band, i)) |
251 | continue; | 258 | continue; |
252 | 259 | ||
@@ -274,7 +281,8 @@ bool rate_control_send_low(struct ieee80211_sta *pubsta, | |||
274 | bool use_basicrate = false; | 281 | bool use_basicrate = false; |
275 | 282 | ||
276 | if (!pubsta || !priv_sta || rc_no_data_or_no_ack_use_min(txrc)) { | 283 | if (!pubsta || !priv_sta || rc_no_data_or_no_ack_use_min(txrc)) { |
277 | __rate_control_send_low(txrc->hw, sband, pubsta, info); | 284 | __rate_control_send_low(txrc->hw, sband, pubsta, info, |
285 | txrc->rate_idx_mask); | ||
278 | 286 | ||
279 | if (!pubsta && txrc->bss) { | 287 | if (!pubsta && txrc->bss) { |
280 | mcast_rate = txrc->bss_conf->mcast_rate[sband->band]; | 288 | mcast_rate = txrc->bss_conf->mcast_rate[sband->band]; |
@@ -656,7 +664,8 @@ void ieee80211_get_tx_rates(struct ieee80211_vif *vif, | |||
656 | rate_control_apply_mask(sdata, sta, sband, info, dest, max_rates); | 664 | rate_control_apply_mask(sdata, sta, sband, info, dest, max_rates); |
657 | 665 | ||
658 | if (dest[0].idx < 0) | 666 | if (dest[0].idx < 0) |
659 | __rate_control_send_low(&sdata->local->hw, sband, sta, info); | 667 | __rate_control_send_low(&sdata->local->hw, sband, sta, info, |
668 | sdata->rc_rateidx_mask[info->band]); | ||
660 | 669 | ||
661 | if (sta) | 670 | if (sta) |
662 | rate_fixup_ratelist(vif, sband, info, dest, max_rates); | 671 | rate_fixup_ratelist(vif, sband, info, dest, max_rates); |