aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2010-06-01 15:33:13 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-06-03 14:14:41 -0400
commit84642d6bdde9164b7905fba03c0691a806788e0c (patch)
treec478140600fc9f0406c3911ce1421ffa3681a4f5 /drivers/net/wireless/ath
parent764580f577a46adce6ad6717a9b34aa8e3a09159 (diff)
ath9k: fix queue stop/start based on the number of pending frames
Because there is a limited number of tx buffers available, once the queue has been filled to a certain point, ath9k needs to stop accepting new frames from mac80211. In order to prevent a full WMM queue from stopping another queue with fewer frames, this patch limits the number of queued frames to a quarter of the total available tx buffers, minus some reserved frames to be used for other purposes (e.g. beacons). Because tx buffers are reserved for frames when they're staged in software queues as well, the actual queue depth cannot be used for this, so this patch stores a reference to the tx queue in the ath_buf struct and keeps track of the total number of pending frames. Signed-off-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h5
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c49
3 files changed, 25 insertions, 37 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index cc6ea4272fd..82aca4b6154 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -136,6 +136,8 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
136#define ATH_MAX_ANTENNA 3 136#define ATH_MAX_ANTENNA 3
137#define ATH_RXBUF 512 137#define ATH_RXBUF 512
138#define ATH_TXBUF 512 138#define ATH_TXBUF 512
139#define ATH_TXBUF_RESERVE 5
140#define ATH_MAX_QDEPTH (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE)
139#define ATH_TXMAXTRY 13 141#define ATH_TXMAXTRY 13
140#define ATH_MGT_TXMAXTRY 4 142#define ATH_MGT_TXMAXTRY 4
141 143
@@ -204,6 +206,7 @@ struct ath_txq {
204 struct list_head txq_fifo_pending; 206 struct list_head txq_fifo_pending;
205 u8 txq_headidx; 207 u8 txq_headidx;
206 u8 txq_tailidx; 208 u8 txq_tailidx;
209 int pending_frames;
207}; 210};
208 211
209struct ath_atx_ac { 212struct ath_atx_ac {
@@ -241,6 +244,7 @@ struct ath_buf {
241 struct ath_buf_state bf_state; 244 struct ath_buf_state bf_state;
242 dma_addr_t bf_dmacontext; 245 dma_addr_t bf_dmacontext;
243 struct ath_wiphy *aphy; 246 struct ath_wiphy *aphy;
247 struct ath_txq *txq;
244}; 248};
245 249
246struct ath_atx_tid { 250struct ath_atx_tid {
@@ -330,7 +334,6 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an);
330void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq); 334void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq);
331int ath_tx_init(struct ath_softc *sc, int nbufs); 335int ath_tx_init(struct ath_softc *sc, int nbufs);
332void ath_tx_cleanup(struct ath_softc *sc); 336void ath_tx_cleanup(struct ath_softc *sc);
333struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb);
334int ath_txq_update(struct ath_softc *sc, int qnum, 337int ath_txq_update(struct ath_softc *sc, int qnum,
335 struct ath9k_tx_queue_info *q); 338 struct ath9k_tx_queue_info *q);
336int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, 339int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 120708d51d4..b8b76dd2c11 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1025,6 +1025,7 @@ static int ath9k_tx(struct ieee80211_hw *hw,
1025 struct ath_tx_control txctl; 1025 struct ath_tx_control txctl;
1026 int padpos, padsize; 1026 int padpos, padsize;
1027 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 1027 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1028 int qnum;
1028 1029
1029 if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) { 1030 if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) {
1030 ath_print(common, ATH_DBG_XMIT, 1031 ath_print(common, ATH_DBG_XMIT,
@@ -1097,11 +1098,8 @@ static int ath9k_tx(struct ieee80211_hw *hw,
1097 memmove(skb->data, skb->data + padsize, padpos); 1098 memmove(skb->data, skb->data + padsize, padpos);
1098 } 1099 }
1099 1100
1100 /* Check if a tx queue is available */ 1101 qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc);
1101 1102 txctl.txq = &sc->tx.txq[qnum];
1102 txctl.txq = ath_test_get_txq(sc, skb);
1103 if (!txctl.txq)
1104 goto exit;
1105 1103
1106 ath_print(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb); 1104 ath_print(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb);
1107 1105
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index f63f6a944d6..7547c8f9a58 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -984,32 +984,6 @@ int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype)
984 return qnum; 984 return qnum;
985} 985}
986 986
987struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb)
988{
989 struct ath_txq *txq = NULL;
990 u16 skb_queue = skb_get_queue_mapping(skb);
991 int qnum;
992
993 qnum = ath_get_hal_qnum(skb_queue, sc);
994 txq = &sc->tx.txq[qnum];
995
996 spin_lock_bh(&txq->axq_lock);
997
998 if (txq->axq_depth >= (ATH_TXBUF - 20)) {
999 ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_XMIT,
1000 "TX queue: %d is full, depth: %d\n",
1001 qnum, txq->axq_depth);
1002 ath_mac80211_stop_queue(sc, skb_queue);
1003 txq->stopped = 1;
1004 spin_unlock_bh(&txq->axq_lock);
1005 return NULL;
1006 }
1007
1008 spin_unlock_bh(&txq->axq_lock);
1009
1010 return txq;
1011}
1012
1013int ath_txq_update(struct ath_softc *sc, int qnum, 987int ath_txq_update(struct ath_softc *sc, int qnum,
1014 struct ath9k_tx_queue_info *qinfo) 988 struct ath9k_tx_queue_info *qinfo)
1015{ 989{
@@ -1809,6 +1783,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
1809 struct ath_wiphy *aphy = hw->priv; 1783 struct ath_wiphy *aphy = hw->priv;
1810 struct ath_softc *sc = aphy->sc; 1784 struct ath_softc *sc = aphy->sc;
1811 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 1785 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
1786 struct ath_txq *txq = txctl->txq;
1812 struct ath_buf *bf; 1787 struct ath_buf *bf;
1813 int r; 1788 int r;
1814 1789
@@ -1818,10 +1793,16 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
1818 return -1; 1793 return -1;
1819 } 1794 }
1820 1795
1796 bf->txq = txctl->txq;
1797 spin_lock_bh(&bf->txq->axq_lock);
1798 if (++bf->txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) {
1799 ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb));
1800 txq->stopped = 1;
1801 }
1802 spin_unlock_bh(&bf->txq->axq_lock);
1803
1821 r = ath_tx_setup_buffer(hw, bf, skb, txctl); 1804 r = ath_tx_setup_buffer(hw, bf, skb, txctl);
1822 if (unlikely(r)) { 1805 if (unlikely(r)) {
1823 struct ath_txq *txq = txctl->txq;
1824
1825 ath_print(common, ATH_DBG_FATAL, "TX mem alloc failure\n"); 1806 ath_print(common, ATH_DBG_FATAL, "TX mem alloc failure\n");
1826 1807
1827 /* upon ath_tx_processq() this TX queue will be resumed, we 1808 /* upon ath_tx_processq() this TX queue will be resumed, we
@@ -1829,7 +1810,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
1829 * we will at least have to run TX completionon one buffer 1810 * we will at least have to run TX completionon one buffer
1830 * on the queue */ 1811 * on the queue */
1831 spin_lock_bh(&txq->axq_lock); 1812 spin_lock_bh(&txq->axq_lock);
1832 if (sc->tx.txq[txq->axq_qnum].axq_depth > 1) { 1813 if (!txq->stopped && txq->axq_depth > 1) {
1833 ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb)); 1814 ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb));
1834 txq->stopped = 1; 1815 txq->stopped = 1;
1835 } 1816 }
@@ -1970,6 +1951,13 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
1970 tx_flags |= ATH_TX_XRETRY; 1951 tx_flags |= ATH_TX_XRETRY;
1971 } 1952 }
1972 1953
1954 if (bf->txq) {
1955 spin_lock_bh(&bf->txq->axq_lock);
1956 bf->txq->pending_frames--;
1957 spin_unlock_bh(&bf->txq->axq_lock);
1958 bf->txq = NULL;
1959 }
1960
1973 dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); 1961 dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE);
1974 ath_tx_complete(sc, skb, bf->aphy, tx_flags); 1962 ath_tx_complete(sc, skb, bf->aphy, tx_flags);
1975 ath_debug_stat_tx(sc, txq, bf, ts); 1963 ath_debug_stat_tx(sc, txq, bf, ts);
@@ -2058,8 +2046,7 @@ static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq)
2058 int qnum; 2046 int qnum;
2059 2047
2060 spin_lock_bh(&txq->axq_lock); 2048 spin_lock_bh(&txq->axq_lock);
2061 if (txq->stopped && 2049 if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) {
2062 sc->tx.txq[txq->axq_qnum].axq_depth <= (ATH_TXBUF - 20)) {
2063 qnum = ath_get_mac80211_qnum(txq->axq_qnum, sc); 2050 qnum = ath_get_mac80211_qnum(txq->axq_qnum, sc);
2064 if (qnum != -1) { 2051 if (qnum != -1) {
2065 ath_mac80211_start_queue(sc, qnum); 2052 ath_mac80211_start_queue(sc, qnum);