aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorRajkumar Manoharan <rmanohar@qca.qualcomm.com>2011-09-16 06:02:34 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-09-19 16:10:11 -0400
commit7cc44ed48d0ec0937c1f098642540b6c9ca38de5 (patch)
tree9c3822fd74a78a110bc390b4fe1101d12f5fd22a /net
parent143bb15de5ea904195d8e52cca7e2edbf5b31159 (diff)
mac80211: Fix regression on queue stop during 2040 bss change
The commit "mac80211: stop tx before doing hw config and rate update" stops the tx queue and call drv_flush so frequently whenever a beacon got received with 11n htcap. This leads to massive "Failed to stop TX DMA" logspam on embedded hw. So the queue stop and flush should be called if and only if there is a change in the channel type. Reported-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: Rajkumar Manoharan <rmanohar@qca.qualcomm.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/mlme.c43
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 */
161static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, 161static 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 */