diff options
-rw-r--r-- | net/mac80211/status.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index a89cca3491b4..e51bd2a1a073 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -187,6 +187,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
187 | int rates_idx = -1; | 187 | int rates_idx = -1; |
188 | bool send_to_cooked; | 188 | bool send_to_cooked; |
189 | bool acked; | 189 | bool acked; |
190 | struct ieee80211_bar *bar; | ||
191 | u16 tid; | ||
190 | 192 | ||
191 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 193 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
192 | if (info->status.rates[i].idx < 0) { | 194 | if (info->status.rates[i].idx < 0) { |
@@ -243,6 +245,22 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
243 | tid, ssn); | 245 | tid, ssn); |
244 | } | 246 | } |
245 | 247 | ||
248 | if (!acked && ieee80211_is_back_req(fc)) { | ||
249 | /* | ||
250 | * BAR failed, let's tear down the BA session as a | ||
251 | * last resort as some STAs (Intel 5100 on Windows) | ||
252 | * can get stuck when the BA window isn't flushed | ||
253 | * correctly. | ||
254 | */ | ||
255 | bar = (struct ieee80211_bar *) skb->data; | ||
256 | if (!(bar->control & IEEE80211_BAR_CTRL_MULTI_TID)) { | ||
257 | tid = (bar->control & | ||
258 | IEEE80211_BAR_CTRL_TID_INFO_MASK) >> | ||
259 | IEEE80211_BAR_CTRL_TID_INFO_SHIFT; | ||
260 | ieee80211_stop_tx_ba_session(&sta->sta, tid); | ||
261 | } | ||
262 | } | ||
263 | |||
246 | if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) { | 264 | if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) { |
247 | ieee80211_handle_filtered_frame(local, sta, skb); | 265 | ieee80211_handle_filtered_frame(local, sta, skb); |
248 | rcu_read_unlock(); | 266 | rcu_read_unlock(); |