From f8c6be2a58f59df6f1d6a97aee4ed8522dd11105 Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@openwrt.org>
Date: Mon, 4 Jul 2011 03:03:12 +0000
Subject: ath9k: merge an upstream change to fix false tx hangs on ar9003

SVN-Revision: 27433
---
 package/mac80211/patches/300-pending_work.patch | 53 ++++++++++++++++++++++++-
 1 file changed, 52 insertions(+), 1 deletion(-)

diff --git a/package/mac80211/patches/300-pending_work.patch b/package/mac80211/patches/300-pending_work.patch
index 285ce69..494c794 100644
--- a/package/mac80211/patches/300-pending_work.patch
+++ b/package/mac80211/patches/300-pending_work.patch
@@ -260,7 +260,15 @@
  	WLAN_STA_BLOCK_BA	= 1<<11,
 --- a/drivers/net/wireless/ath/ath9k/beacon.c
 +++ b/drivers/net/wireless/ath/ath9k/beacon.c
-@@ -384,7 +384,9 @@ void ath_beacon_tasklet(unsigned long da
+@@ -360,6 +360,7 @@ void ath_beacon_tasklet(unsigned long da
+ 	struct ath_common *common = ath9k_hw_common(ah);
+ 	struct ath_buf *bf = NULL;
+ 	struct ieee80211_vif *vif;
++	struct ath_tx_status ts;
+ 	int slot;
+ 	u32 bfaddr, bc = 0;
+ 
+@@ -384,7 +385,9 @@ void ath_beacon_tasklet(unsigned long da
  			ath_dbg(common, ATH_DBG_BSTUCK,
  				"beacon is officially stuck\n");
  			sc->sc_flags |= SC_OP_TSF_RESET;
@@ -270,6 +278,18 @@
  		}
  
  		return;
+@@ -464,6 +467,11 @@ void ath_beacon_tasklet(unsigned long da
+ 		ath9k_hw_txstart(ah, sc->beacon.beaconq);
+ 
+ 		sc->beacon.ast_be_xmit += bc;     /* XXX per-vif? */
++		if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
++			spin_lock_bh(&sc->sc_pcu_lock);
++			ath9k_hw_txprocdesc(ah, bf->bf_desc, (void *)&ts);
++			spin_unlock_bh(&sc->sc_pcu_lock);
++		}
+ 	}
+ }
+ 
 --- a/drivers/net/wireless/ath/ath9k/main.c
 +++ b/drivers/net/wireless/ath/ath9k/main.c
 @@ -617,8 +617,11 @@ void ath_hw_check(struct work_struct *wo
@@ -481,3 +501,34 @@
  		}
  
  		kfree(chinfo[pier].pd_curves);
+--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+@@ -229,6 +229,7 @@ static void ar9003_hw_fill_txdesc(struct
+ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
+ 				 struct ath_tx_status *ts)
+ {
++	struct ar9003_txc *txc = (struct ar9003_txc *) ds;
+ 	struct ar9003_txs *ads;
+ 	u32 status;
+ 
+@@ -238,7 +239,11 @@ static int ar9003_hw_proc_txdesc(struct 
+ 	if ((status & AR_TxDone) == 0)
+ 		return -EINPROGRESS;
+ 
+-	ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
++	ts->qid = MS(ads->ds_info, AR_TxQcuNum);
++	if (!txc || (MS(txc->info, AR_TxQcuNum) == ts->qid))
++		ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
++	else
++		return -ENOENT;
+ 
+ 	if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) ||
+ 	    (MS(ads->ds_info, AR_TxRxDesc) != 1)) {
+@@ -254,7 +259,6 @@ static int ar9003_hw_proc_txdesc(struct 
+ 	ts->ts_seqnum = MS(status, AR_SeqNum);
+ 	ts->tid = MS(status, AR_TxTid);
+ 
+-	ts->qid = MS(ads->ds_info, AR_TxQcuNum);
+ 	ts->desc_id = MS(ads->status1, AR_TxDescId);
+ 	ts->ts_tstamp = ads->status4;
+ 	ts->ts_status = 0;
-- 
cgit v1.1