aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/status.c18
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();