carl9170: Fix tx aggregation problems with some clients
Christian Lamparter [Tue, 29 Mar 2011 11:43:14 +0000 (13:43 +0200)]
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 c6a5fae..9cad061 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 ede3d7e..89fe60a 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 0ef70b6..cb70ed7 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);