diff options
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r-- | net/mac80211/mlme.c | 43 |
1 files changed, 24 insertions, 19 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 2f92ae2f9706..1a59fb6630d4 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -160,7 +160,8 @@ static int ecw2cw(int ecw) | |||
160 | */ | 160 | */ |
161 | static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | 161 | static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, |
162 | struct ieee80211_ht_info *hti, | 162 | struct ieee80211_ht_info *hti, |
163 | const u8 *bssid, u16 ap_ht_cap_flags) | 163 | const u8 *bssid, u16 ap_ht_cap_flags, |
164 | bool beacon_htcap_ie) | ||
164 | { | 165 | { |
165 | struct ieee80211_local *local = sdata->local; | 166 | struct ieee80211_local *local = sdata->local; |
166 | struct ieee80211_supported_band *sband; | 167 | struct ieee80211_supported_band *sband; |
@@ -232,6 +233,21 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
232 | WARN_ON(!ieee80211_set_channel_type(local, sdata, channel_type)); | 233 | WARN_ON(!ieee80211_set_channel_type(local, sdata, channel_type)); |
233 | } | 234 | } |
234 | 235 | ||
236 | if (beacon_htcap_ie && (prev_chantype != channel_type)) { | ||
237 | /* | ||
238 | * Whenever the AP announces the HT mode change that can be | ||
239 | * 40MHz intolerant or etc., it would be safer to stop tx | ||
240 | * queues before doing hw config to avoid buffer overflow. | ||
241 | */ | ||
242 | ieee80211_stop_queues_by_reason(&sdata->local->hw, | ||
243 | IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE); | ||
244 | |||
245 | /* flush out all packets */ | ||
246 | synchronize_net(); | ||
247 | |||
248 | drv_flush(local, false); | ||
249 | } | ||
250 | |||
235 | /* channel_type change automatically detected */ | 251 | /* channel_type change automatically detected */ |
236 | ieee80211_hw_config(local, 0); | 252 | ieee80211_hw_config(local, 0); |
237 | 253 | ||
@@ -243,6 +259,10 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
243 | IEEE80211_RC_HT_CHANGED, | 259 | IEEE80211_RC_HT_CHANGED, |
244 | channel_type); | 260 | channel_type); |
245 | rcu_read_unlock(); | 261 | rcu_read_unlock(); |
262 | |||
263 | if (beacon_htcap_ie) | ||
264 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | ||
265 | IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE); | ||
246 | } | 266 | } |
247 | 267 | ||
248 | ht_opmode = le16_to_cpu(hti->operation_mode); | 268 | ht_opmode = le16_to_cpu(hti->operation_mode); |
@@ -1588,7 +1608,8 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1588 | (sdata->local->hw.queues >= 4) && | 1608 | (sdata->local->hw.queues >= 4) && |
1589 | !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) | 1609 | !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) |
1590 | changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, | 1610 | changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, |
1591 | cbss->bssid, ap_ht_cap_flags); | 1611 | cbss->bssid, ap_ht_cap_flags, |
1612 | false); | ||
1592 | 1613 | ||
1593 | /* set AID and assoc capability, | 1614 | /* set AID and assoc capability, |
1594 | * ieee80211_set_associated() will tell the driver */ | 1615 | * ieee80211_set_associated() will tell the driver */ |
@@ -1921,24 +1942,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1921 | 1942 | ||
1922 | rcu_read_unlock(); | 1943 | rcu_read_unlock(); |
1923 | 1944 | ||
1924 | /* | ||
1925 | * Whenever the AP announces the HT mode change that can be | ||
1926 | * 40MHz intolerant or etc., it would be safer to stop tx | ||
1927 | * queues before doing hw config to avoid buffer overflow. | ||
1928 | */ | ||
1929 | ieee80211_stop_queues_by_reason(&sdata->local->hw, | ||
1930 | IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE); | ||
1931 | |||
1932 | /* flush out all packets */ | ||
1933 | synchronize_net(); | ||
1934 | |||
1935 | drv_flush(local, false); | ||
1936 | |||
1937 | changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, | 1945 | changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, |
1938 | bssid, ap_ht_cap_flags); | 1946 | bssid, ap_ht_cap_flags, true); |
1939 | |||
1940 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | ||
1941 | IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE); | ||
1942 | } | 1947 | } |
1943 | 1948 | ||
1944 | /* Note: country IE parsing is done for us by cfg80211 */ | 1949 | /* Note: country IE parsing is done for us by cfg80211 */ |