summaryrefslogtreecommitdiffstats
path: root/net/mac80211/status.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/status.c')
-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 a89cca3491b..e51bd2a1a07 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)
int rates_idx = -1;
bool send_to_cooked;
bool acked;
+ struct ieee80211_bar *bar;
+ u16 tid;
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
if (info->status.rates[i].idx < 0) {
@@ -243,6 +245,22 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
tid, ssn);
}
+ if (!acked && ieee80211_is_back_req(fc)) {
+ /*
+ * BAR failed, let's tear down the BA session as a
+ * last resort as some STAs (Intel 5100 on Windows)
+ * can get stuck when the BA window isn't flushed
+ * correctly.
+ */
+ bar = (struct ieee80211_bar *) skb->data;
+ if (!(bar->control & IEEE80211_BAR_CTRL_MULTI_TID)) {
+ tid = (bar->control &
+ IEEE80211_BAR_CTRL_TID_INFO_MASK) >>
+ IEEE80211_BAR_CTRL_TID_INFO_SHIFT;
+ ieee80211_stop_tx_ba_session(&sta->sta, tid);
+ }
+ }
+
if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
ieee80211_handle_filtered_frame(local, sta, skb);
rcu_read_unlock();