carl9170: Fix tx aggregation problems with some clients
authorChristian Lamparter <chunkeey@googlemail.com>
Tue, 29 Mar 2011 11:43:14 +0000 (13:43 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 29 Mar 2011 19:45:14 +0000 (15:45 -0400)
Some clients seem to rely upon the reception of BlockAckReqs to flush
their rx reorder buffer. In order to fix aggregation for these clients
carl9170 should set IEEE80211_TX_STAT_AMPDU_NO_BACK to generate a
BlockAckReq if the transmission of an AMPDU subframe fails.

This fixes aggregation problems with Intel 5100 Windows STAs (and maybe
others as well).

Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/carl9170/carl9170.h
drivers/net/wireless/ath/carl9170/main.c
drivers/net/wireless/ath/carl9170/tx.c

index c6a5fae634a0f14718ff60e212ad20c123a58ca0..9cad061cc1d2c7743e74430f3e9943310240a69a 100644 (file)
@@ -443,6 +443,7 @@ struct carl9170_ba_stats {
        u8 ampdu_len;
        u8 ampdu_ack_len;
        bool clear;
+       bool req;
 };
 
 struct carl9170_sta_info {
index ede3d7e5a048d3a356cc56890318ea391df81241..89fe60accf8550f7a7234d7c0542eec7e1670bb3 100644 (file)
@@ -1355,6 +1355,7 @@ static int carl9170_op_ampdu_action(struct ieee80211_hw *hw,
                tid_info = rcu_dereference(sta_info->agg[tid]);
 
                sta_info->stats[tid].clear = true;
+               sta_info->stats[tid].req = false;
 
                if (tid_info) {
                        bitmap_zero(tid_info->bitmap, CARL9170_BAW_SIZE);
index 0ef70b6fc512b672d97360e0b48bab40796a2794..cb70ed7ec5ccff939c7c29b6cd340ecba07d0933 100644 (file)
@@ -383,6 +383,7 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar,
 
        if (sta_info->stats[tid].clear) {
                sta_info->stats[tid].clear = false;
+               sta_info->stats[tid].req = false;
                sta_info->stats[tid].ampdu_len = 0;
                sta_info->stats[tid].ampdu_ack_len = 0;
        }
@@ -391,10 +392,16 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar,
        if (txinfo->status.rates[0].count == 1)
                sta_info->stats[tid].ampdu_ack_len++;
 
+       if (!(txinfo->flags & IEEE80211_TX_STAT_ACK))
+               sta_info->stats[tid].req = true;
+
        if (super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_IMM_BA)) {
                super->s.rix = sta_info->stats[tid].ampdu_len;
                super->s.cnt = sta_info->stats[tid].ampdu_ack_len;
                txinfo->flags |= IEEE80211_TX_STAT_AMPDU;
+               if (sta_info->stats[tid].req)
+                       txinfo->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
+
                sta_info->stats[tid].clear = true;
        }
        spin_unlock_bh(&tid_info->lock);