summaryrefslogtreecommitdiffstats
path: root/net/mac80211/agg-rx.c
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2014-07-16 12:09:31 +0200
committerJohannes Berg <johannes.berg@intel.com>2014-07-21 16:17:26 +0200
commit83eb935ec74a91468776cd86415abcb6ee23cca8 (patch)
treee0977824eadbba57f30adaa47f7d31c2a60ed6f1 /net/mac80211/agg-rx.c
parentmac80211: remove useless NULL checks (diff)
downloadlinux-83eb935ec74a91468776cd86415abcb6ee23cca8.tar.xz
linux-83eb935ec74a91468776cd86415abcb6ee23cca8.zip
mac80211: fix Rx reordering with RX_FLAG_AMSDU_MORE
Some drivers (e.g. ath10k) report A-MSDU subframes individually with identical seqno. The A-MPDU Rx reorder code did not account for that which made it practically unusable with drivers using RX_FLAG_AMSDU_MORE because it would end up dropping a lot of frames resulting in confusion in upper network transport layers. Signed-off-by: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/agg-rx.c')
-rw-r--r--net/mac80211/agg-rx.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 31bf2586fb84..d38c49b644cd 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -52,7 +52,7 @@ static void ieee80211_free_tid_rx(struct rcu_head *h)
del_timer_sync(&tid_rx->reorder_timer);
for (i = 0; i < tid_rx->buf_size; i++)
- dev_kfree_skb(tid_rx->reorder_buf[i]);
+ __skb_queue_purge(&tid_rx->reorder_buf[i]);
kfree(tid_rx->reorder_buf);
kfree(tid_rx->reorder_time);
kfree(tid_rx);
@@ -232,7 +232,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
struct tid_ampdu_rx *tid_agg_rx;
u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num, status;
u8 dialog_token;
- int ret = -EOPNOTSUPP;
+ int i, ret = -EOPNOTSUPP;
/* extract session parameters from addba request frame */
dialog_token = mgmt->u.action.u.addba_req.dialog_token;
@@ -308,7 +308,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
/* prepare reordering buffer */
tid_agg_rx->reorder_buf =
- kcalloc(buf_size, sizeof(struct sk_buff *), GFP_KERNEL);
+ kcalloc(buf_size, sizeof(struct sk_buff_head), GFP_KERNEL);
tid_agg_rx->reorder_time =
kcalloc(buf_size, sizeof(unsigned long), GFP_KERNEL);
if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) {
@@ -318,6 +318,9 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
goto end;
}
+ for (i = 0; i < buf_size; i++)
+ __skb_queue_head_init(&tid_agg_rx->reorder_buf[i]);
+
ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START,
&sta->sta, tid, &start_seq_num, 0);
ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n",