From 8371085c8b28639be8a72f3bbbea7cc1a1925eb9 Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@openwrt.org>
Date: Sat, 9 Apr 2011 15:22:01 +0000
Subject: [PATCH] ath9k: properly count retries when frames are filtered due to
 excessive retries when a client is not in powersave mode

SVN-Revision: 26545
---
 .../521-ath9k_fix_ap_ps_buffering.patch       | 55 +++++++++++++------
 1 file changed, 39 insertions(+), 16 deletions(-)

diff --git a/package/mac80211/patches/521-ath9k_fix_ap_ps_buffering.patch b/package/mac80211/patches/521-ath9k_fix_ap_ps_buffering.patch
index 8f6249c84c..cc956ed279 100644
--- a/package/mac80211/patches/521-ath9k_fix_ap_ps_buffering.patch
+++ b/package/mac80211/patches/521-ath9k_fix_ap_ps_buffering.patch
@@ -75,20 +75,43 @@
  
  	skb = bf->bf_mpdu;
  	hdr = (struct ieee80211_hdr *)skb->data;
-@@ -442,7 +443,11 @@ static void ath_tx_complete_aggr(struct 
+@@ -441,22 +442,24 @@ static void ath_tx_complete_aggr(struct 
+ 			/* transmit completion */
  			acked_cnt++;
  		} else {
- 			if (!(tid->state & AGGR_CLEANUP) && retry) {
+-			if (!(tid->state & AGGR_CLEANUP) && retry) {
 -				if (fi->retries < ATH_MAX_SW_RETRIES) {
-+				if (ts->ts_status & ATH9K_TXERR_FILT) {
-+					if (!an->sleeping)
-+						clear_filter = true;
-+					txpending = 1;
-+				} else if (fi->retries < ATH_MAX_SW_RETRIES) {
- 					ath_tx_set_retry(sc, txq, bf->bf_mpdu);
- 					txpending = 1;
- 				} else {
-@@ -496,6 +501,7 @@ static void ath_tx_complete_aggr(struct 
+-					ath_tx_set_retry(sc, txq, bf->bf_mpdu);
+-					txpending = 1;
+-				} else {
+-					bf->bf_state.bf_type |= BUF_XRETRY;
+-					txfail = 1;
+-					sendbar = 1;
+-					txfail_cnt++;
+-				}
+-			} else {
++			if ((tid->state & AGGR_CLEANUP) || !retry) {
+ 				/*
+ 				 * cleanup in progress, just fail
+ 				 * the un-acked sub-frames
+ 				 */
+ 				txfail = 1;
++			} else if (fi->retries < ATH_MAX_SW_RETRIES) {
++				if (!(ts->ts_status & ATH9K_TXERR_FILT) ||
++				    !an->sleeping)
++					ath_tx_set_retry(sc, txq, bf->bf_mpdu);
++
++				clear_filter = true;
++				txpending = 1;
++			} else {
++				bf->bf_state.bf_type |= BUF_XRETRY;
++				txfail = 1;
++				sendbar = 1;
++				txfail_cnt++;
+ 			}
+ 		}
+ 
+@@ -496,6 +499,7 @@ static void ath_tx_complete_aggr(struct 
  				!txfail, sendbar);
  		} else {
  			/* retry the un-acked ones */
@@ -96,7 +119,7 @@
  			if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
  				if (bf->bf_next == NULL && bf_last->bf_stale) {
  					struct ath_buf *tbf;
-@@ -546,7 +552,12 @@ static void ath_tx_complete_aggr(struct 
+@@ -546,7 +550,12 @@ static void ath_tx_complete_aggr(struct 
  
  	/* prepend un-acked frames to the beginning of the pending frame queue */
  	if (!list_empty(&bf_pending)) {
@@ -109,7 +132,7 @@
  		list_splice(&bf_pending, &tid->buf_q);
  		ath_tx_queue_tid(txq, tid);
  		spin_unlock_bh(&txq->axq_lock);
-@@ -816,6 +827,11 @@ static void ath_tx_sched_aggr(struct ath
+@@ -816,6 +825,11 @@ static void ath_tx_sched_aggr(struct ath
  		bf = list_first_entry(&bf_q, struct ath_buf, list);
  		bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list);
  
@@ -121,7 +144,7 @@
  		/* if only one frame, send as non-aggregate */
  		if (bf == bf->bf_lastbf) {
  			fi = get_frame_info(bf->bf_mpdu);
-@@ -896,6 +912,67 @@ void ath_tx_aggr_stop(struct ath_softc *
+@@ -896,6 +910,67 @@ void ath_tx_aggr_stop(struct ath_softc *
  	ath_tx_flush_tid(sc, txtid);
  }
  
@@ -189,7 +212,7 @@
  void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
  {
  	struct ath_atx_tid *txtid;
-@@ -1491,7 +1568,6 @@ static int setup_tx_flags(struct sk_buff
+@@ -1491,7 +1566,6 @@ static int setup_tx_flags(struct sk_buff
  	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
  	int flags = 0;
  
@@ -197,7 +220,7 @@
  	flags |= ATH9K_TXDESC_INTREQ;
  
  	if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
-@@ -1754,6 +1830,9 @@ static void ath_tx_start_dma(struct ath_
+@@ -1754,6 +1828,9 @@ static void ath_tx_start_dma(struct ath_
  		if (txctl->paprd)
  			bf->bf_state.bfs_paprd_timestamp = jiffies;
  
-- 
2.30.2