From 691b253e47367f64097023ba2afcc595ca120786 Mon Sep 17 00:00:00 2001
From: nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Date: Mon, 16 Apr 2012 21:08:41 +0000
Subject: mac80211: update to wireless-testing 2012-04-13

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@31322 3c298f89-4303-0410-b956-a3cf2f4a3e73
---
 .../mac80211/patches/530-ath9k_limit_qlen.patch    | 143 +++++++++++++++++++++
 1 file changed, 143 insertions(+)
 create mode 100644 package/mac80211/patches/530-ath9k_limit_qlen.patch

(limited to 'package/mac80211/patches/530-ath9k_limit_qlen.patch')

diff --git a/package/mac80211/patches/530-ath9k_limit_qlen.patch b/package/mac80211/patches/530-ath9k_limit_qlen.patch
new file mode 100644
index 000000000..5c649ce0e
--- /dev/null
+++ b/package/mac80211/patches/530-ath9k_limit_qlen.patch
@@ -0,0 +1,143 @@
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -243,6 +243,7 @@ struct ath_atx_tid {
+ 	struct ath_node *an;
+ 	struct ath_atx_ac *ac;
+ 	unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
++	int buf_pending;
+ 	int bar_index;
+ 	u16 seq_start;
+ 	u16 seq_next;
+@@ -289,6 +290,9 @@ struct ath_tx_control {
+  *  (axq_qnum).
+  */
+ struct ath_tx {
++	u32 qlen_single;
++	u32 qlen_aggr;
++
+ 	u16 seq_no;
+ 	u32 txqsetup;
+ 	spinlock_t txbuflock;
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -1658,6 +1658,10 @@ int ath9k_init_debug(struct ath_hw *ah)
+ 			    &fops_interrupt);
+ 	debugfs_create_file("xmit", S_IRUSR, sc->debug.debugfs_phy, sc,
+ 			    &fops_xmit);
++	debugfs_create_u32("qlen_single", S_IRUSR | S_IWUSR,
++			   sc->debug.debugfs_phy, &sc->tx.qlen_single);
++	debugfs_create_u32("qlen_aggr", S_IRUSR | S_IWUSR,
++			   sc->debug.debugfs_phy, &sc->tx.qlen_aggr);
+ 	debugfs_create_file("stations", S_IRUSR, sc->debug.debugfs_phy, sc,
+ 			    &fops_stations);
+ 	debugfs_create_file("misc", S_IRUSR, sc->debug.debugfs_phy, sc,
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -392,6 +392,14 @@ static void ath_tx_count_frames(struct a
+ 	}
+ }
+ 
++static struct ath_atx_tid *ath_get_tid(struct ath_node *an, struct sk_buff *skb)
++{
++	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
++	u8 tidno;
++
++	tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
++	return ATH_AN_2_TID(an, tidno);
++}
+ 
+ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
+ 				 struct ath_buf *bf, struct list_head *bf_q,
+@@ -486,6 +494,8 @@ static void ath_tx_complete_aggr(struct 
+ 	__skb_queue_head_init(&bf_pending);
+ 
+ 	ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
++	tid->buf_pending -= nframes;
++
+ 	while (bf) {
+ 		u16 seqno = bf->bf_state.seqno;
+ 
+@@ -884,6 +894,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_
+ 			ath_tx_addto_baw(sc, tid, seqno);
+ 		bf->bf_state.ndelim = ndelim;
+ 
++		tid->buf_pending++;
+ 		__skb_unlink(skb, &tid->buf_q);
+ 		list_add_tail(&bf->list, bf_q);
+ 		if (bf_prev)
+@@ -1737,6 +1748,8 @@ static void ath_tx_send_ampdu(struct ath
+ 	/* Add sub-frame to BAW */
+ 	ath_tx_addto_baw(sc, tid, bf->bf_state.seqno);
+ 
++	tid->buf_pending++;
++
+ 	/* Queue to h/w without aggregation */
+ 	TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
+ 	bf->bf_lastbf = bf;
+@@ -1861,22 +1874,11 @@ error:
+ 
+ /* FIXME: tx power */
+ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
+-			     struct ath_tx_control *txctl)
++			     struct ath_tx_control *txctl,
++			     struct ath_atx_tid *tid)
+ {
+ 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+-	struct ath_atx_tid *tid = NULL;
+ 	struct ath_buf *bf;
+-	u8 tidno;
+-
+-	if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) && txctl->an &&
+-		ieee80211_is_data_qos(hdr->frame_control)) {
+-		tidno = ieee80211_get_qos_ctl(hdr)[0] &
+-			IEEE80211_QOS_CTL_TID_MASK;
+-		tid = ATH_AN_2_TID(txctl->an, tidno);
+-
+-		WARN_ON(tid->ac->txq != txctl->txq);
+-	}
+ 
+ 	if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
+ 		/*
+@@ -1908,6 +1910,7 @@ int ath_tx_start(struct ieee80211_hw *hw
+ 	struct ieee80211_vif *vif = info->control.vif;
+ 	struct ath_softc *sc = hw->priv;
+ 	struct ath_txq *txq = txctl->txq;
++	struct ath_atx_tid *tid = NULL;
+ 	int padpos, padsize;
+ 	int frmlen = skb->len + FCS_LEN;
+ 	int q;
+@@ -1950,6 +1953,24 @@ int ath_tx_start(struct ieee80211_hw *hw
+ 
+ 	setup_frame_info(hw, skb, frmlen);
+ 
++	if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) && txctl->an &&
++	    ieee80211_is_data_qos(hdr->frame_control)) {
++		tid = ath_get_tid(txctl->an, skb);
++
++		WARN_ON(tid->ac->txq != txq);
++	}
++
++	if ((info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
++		if (sc->tx.qlen_aggr > 0 && skb_queue_len(&tid->buf_q) +
++		    tid->buf_pending >= sc->tx.qlen_aggr)
++			return -ENOMEM;
++	} else {
++		if (sc->tx.qlen_single > 0 &&
++		    txq->axq_depth - txq->axq_ampdu_depth >=
++		      sc->tx.qlen_single)
++			return -ENOMEM;
++	}
++
+ 	/*
+ 	 * At this point, the vif, hw_key and sta pointers in the tx control
+ 	 * info are no longer valid (overwritten by the ath_frame_info data.
+@@ -1964,7 +1985,7 @@ int ath_tx_start(struct ieee80211_hw *hw
+ 		txq->stopped = true;
+ 	}
+ 
+-	ath_tx_start_dma(sc, skb, txctl);
++	ath_tx_start_dma(sc, skb, txctl, tid);
+ 
+ 	ath_txq_unlock(sc, txq);
+ 
-- 
cgit v1.2.3