diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/mlme.c | 97 |
1 files changed, 49 insertions, 48 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 81e0124e68ce..39c13939008b 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1344,12 +1344,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
1344 | bss_conf->dtim_period = 0; | 1344 | bss_conf->dtim_period = 0; |
1345 | 1345 | ||
1346 | bss_conf->assoc = 1; | 1346 | bss_conf->assoc = 1; |
1347 | /* | ||
1348 | * For now just always ask the driver to update the basic rateset | ||
1349 | * when we have associated, we aren't checking whether it actually | ||
1350 | * changed or not. | ||
1351 | */ | ||
1352 | bss_info_changed |= BSS_CHANGED_BASIC_RATES; | ||
1353 | 1347 | ||
1354 | /* Tell the driver to monitor connection quality (if supported) */ | 1348 | /* Tell the driver to monitor connection quality (if supported) */ |
1355 | if (sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI && | 1349 | if (sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI && |
@@ -2001,15 +1995,12 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
2001 | struct ieee80211_supported_band *sband; | 1995 | struct ieee80211_supported_band *sband; |
2002 | struct sta_info *sta; | 1996 | struct sta_info *sta; |
2003 | u8 *pos; | 1997 | u8 *pos; |
2004 | u32 rates, basic_rates; | ||
2005 | u16 capab_info, aid; | 1998 | u16 capab_info, aid; |
2006 | struct ieee802_11_elems elems; | 1999 | struct ieee802_11_elems elems; |
2007 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; | 2000 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; |
2008 | u32 changed = 0; | 2001 | u32 changed = 0; |
2009 | int err; | 2002 | int err; |
2010 | bool have_higher_than_11mbit = false; | ||
2011 | u16 ap_ht_cap_flags; | 2003 | u16 ap_ht_cap_flags; |
2012 | int min_rate = INT_MAX, min_rate_index = -1; | ||
2013 | 2004 | ||
2014 | /* AssocResp and ReassocResp have identical structure */ | 2005 | /* AssocResp and ReassocResp have identical structure */ |
2015 | 2006 | ||
@@ -2054,39 +2045,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
2054 | return false; | 2045 | return false; |
2055 | } | 2046 | } |
2056 | 2047 | ||
2057 | rates = 0; | ||
2058 | basic_rates = 0; | ||
2059 | sband = local->hw.wiphy->bands[local->oper_channel->band]; | 2048 | sband = local->hw.wiphy->bands[local->oper_channel->band]; |
2060 | 2049 | ||
2061 | ieee80211_get_rates(sband, elems.supp_rates, elems.supp_rates_len, | ||
2062 | &rates, &basic_rates, &have_higher_than_11mbit, | ||
2063 | &min_rate, &min_rate_index); | ||
2064 | |||
2065 | ieee80211_get_rates(sband, elems.ext_supp_rates, | ||
2066 | elems.ext_supp_rates_len, &rates, &basic_rates, | ||
2067 | &have_higher_than_11mbit, | ||
2068 | &min_rate, &min_rate_index); | ||
2069 | |||
2070 | /* | ||
2071 | * some buggy APs don't advertise basic_rates. use the lowest | ||
2072 | * supported rate instead. | ||
2073 | */ | ||
2074 | if (unlikely(!basic_rates) && min_rate_index >= 0) { | ||
2075 | printk(KERN_DEBUG "%s: No basic rates in AssocResp. " | ||
2076 | "Using min supported rate instead.\n", sdata->name); | ||
2077 | basic_rates = BIT(min_rate_index); | ||
2078 | } | ||
2079 | |||
2080 | sta->sta.supp_rates[local->oper_channel->band] = rates; | ||
2081 | sdata->vif.bss_conf.basic_rates = basic_rates; | ||
2082 | |||
2083 | /* cf. IEEE 802.11 9.2.12 */ | ||
2084 | if (local->oper_channel->band == IEEE80211_BAND_2GHZ && | ||
2085 | have_higher_than_11mbit) | ||
2086 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; | ||
2087 | else | ||
2088 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; | ||
2089 | |||
2090 | if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) | 2050 | if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) |
2091 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, | 2051 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, |
2092 | elems.ht_cap_elem, &sta->sta.ht_cap); | 2052 | elems.ht_cap_elem, &sta->sta.ht_cap); |
@@ -3090,10 +3050,11 @@ int ieee80211_max_network_latency(struct notifier_block *nb, | |||
3090 | } | 3050 | } |
3091 | 3051 | ||
3092 | static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | 3052 | static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, |
3093 | struct cfg80211_bss *bss, bool assoc) | 3053 | struct cfg80211_bss *cbss, bool assoc) |
3094 | { | 3054 | { |
3095 | struct ieee80211_local *local = sdata->local; | 3055 | struct ieee80211_local *local = sdata->local; |
3096 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 3056 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
3057 | struct ieee80211_bss *bss = (void *)cbss->priv; | ||
3097 | struct sta_info *sta; | 3058 | struct sta_info *sta; |
3098 | bool have_sta = false; | 3059 | bool have_sta = false; |
3099 | int err; | 3060 | int err; |
@@ -3103,12 +3064,12 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3103 | 3064 | ||
3104 | if (assoc) { | 3065 | if (assoc) { |
3105 | rcu_read_lock(); | 3066 | rcu_read_lock(); |
3106 | have_sta = sta_info_get(sdata, bss->bssid); | 3067 | have_sta = sta_info_get(sdata, cbss->bssid); |
3107 | rcu_read_unlock(); | 3068 | rcu_read_unlock(); |
3108 | } | 3069 | } |
3109 | 3070 | ||
3110 | if (!have_sta) { | 3071 | if (!have_sta) { |
3111 | sta = sta_info_alloc(sdata, bss->bssid, GFP_KERNEL); | 3072 | sta = sta_info_alloc(sdata, cbss->bssid, GFP_KERNEL); |
3112 | if (!sta) | 3073 | if (!sta) |
3113 | return -ENOMEM; | 3074 | return -ENOMEM; |
3114 | } | 3075 | } |
@@ -3118,13 +3079,53 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3118 | mutex_unlock(&local->mtx); | 3079 | mutex_unlock(&local->mtx); |
3119 | 3080 | ||
3120 | /* switch to the right channel */ | 3081 | /* switch to the right channel */ |
3121 | local->oper_channel = bss->channel; | 3082 | local->oper_channel = cbss->channel; |
3122 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 3083 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
3123 | 3084 | ||
3124 | if (!have_sta) { | 3085 | if (!have_sta) { |
3125 | /* set BSSID - if STA already there this will be set too */ | 3086 | struct ieee80211_supported_band *sband; |
3126 | memcpy(ifmgd->bssid, bss->bssid, ETH_ALEN); | 3087 | u32 rates = 0, basic_rates = 0; |
3127 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); | 3088 | bool have_higher_than_11mbit; |
3089 | int min_rate = INT_MAX, min_rate_index = -1; | ||
3090 | |||
3091 | sband = sdata->local->hw.wiphy->bands[cbss->channel->band]; | ||
3092 | |||
3093 | ieee80211_get_rates(sband, bss->supp_rates, | ||
3094 | bss->supp_rates_len, | ||
3095 | &rates, &basic_rates, | ||
3096 | &have_higher_than_11mbit, | ||
3097 | &min_rate, &min_rate_index); | ||
3098 | |||
3099 | /* | ||
3100 | * This used to be a workaround for basic rates missing | ||
3101 | * in the association response frame. Now that we no | ||
3102 | * longer use the basic rates from there, it probably | ||
3103 | * doesn't happen any more, but keep the workaround so | ||
3104 | * in case some *other* APs are buggy in different ways | ||
3105 | * we can connect -- with a warning. | ||
3106 | */ | ||
3107 | if (!basic_rates && min_rate_index >= 0) { | ||
3108 | printk(KERN_DEBUG | ||
3109 | "%s: No basic rates, using min rate instead.\n", | ||
3110 | sdata->name); | ||
3111 | basic_rates = BIT(min_rate_index); | ||
3112 | } | ||
3113 | |||
3114 | sta->sta.supp_rates[cbss->channel->band] = rates; | ||
3115 | sdata->vif.bss_conf.basic_rates = basic_rates; | ||
3116 | |||
3117 | /* cf. IEEE 802.11 9.2.12 */ | ||
3118 | if (local->oper_channel->band == IEEE80211_BAND_2GHZ && | ||
3119 | have_higher_than_11mbit) | ||
3120 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; | ||
3121 | else | ||
3122 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; | ||
3123 | |||
3124 | memcpy(ifmgd->bssid, cbss->bssid, ETH_ALEN); | ||
3125 | |||
3126 | /* tell driver about BSSID and basic rates */ | ||
3127 | ieee80211_bss_info_change_notify(sdata, | ||
3128 | BSS_CHANGED_BSSID | BSS_CHANGED_BASIC_RATES); | ||
3128 | 3129 | ||
3129 | if (assoc) | 3130 | if (assoc) |
3130 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); | 3131 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); |
@@ -3138,7 +3139,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3138 | return err; | 3139 | return err; |
3139 | } | 3140 | } |
3140 | } else | 3141 | } else |
3141 | WARN_ON_ONCE(compare_ether_addr(ifmgd->bssid, bss->bssid)); | 3142 | WARN_ON_ONCE(compare_ether_addr(ifmgd->bssid, cbss->bssid)); |
3142 | 3143 | ||
3143 | return 0; | 3144 | return 0; |
3144 | } | 3145 | } |