mirror of https://github.com/hak5/openwrt.git
ath9k: fix queue stopping/starting logic, should slightly reduce RAM usage under load and make throughput more smooth
SVN-Revision: 21650lede-17.01
parent
4586129989
commit
82e32fbb71
|
@ -0,0 +1,144 @@
|
|||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
@@ -137,6 +137,8 @@ void ath_descdma_cleanup(struct ath_soft
|
||||
#define ATH_MAX_ANTENNA 3
|
||||
#define ATH_RXBUF 512
|
||||
#define ATH_TXBUF 512
|
||||
+#define ATH_TXBUF_RESERVE 5
|
||||
+#define ATH_MAX_QDEPTH (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE)
|
||||
#define ATH_TXMAXTRY 13
|
||||
#define ATH_MGT_TXMAXTRY 4
|
||||
|
||||
@@ -205,6 +207,7 @@ struct ath_txq {
|
||||
struct list_head txq_fifo_pending;
|
||||
u8 txq_headidx;
|
||||
u8 txq_tailidx;
|
||||
+ int pending_frames;
|
||||
};
|
||||
|
||||
struct ath_atx_ac {
|
||||
@@ -242,6 +245,7 @@ struct ath_buf {
|
||||
struct ath_buf_state bf_state;
|
||||
dma_addr_t bf_dmacontext;
|
||||
struct ath_wiphy *aphy;
|
||||
+ struct ath_txq *txq;
|
||||
};
|
||||
|
||||
struct ath_atx_tid {
|
||||
@@ -331,7 +335,6 @@ void ath_tx_node_cleanup(struct ath_soft
|
||||
void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq);
|
||||
int ath_tx_init(struct ath_softc *sc, int nbufs);
|
||||
void ath_tx_cleanup(struct ath_softc *sc);
|
||||
-struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb);
|
||||
int ath_txq_update(struct ath_softc *sc, int qnum,
|
||||
struct ath9k_tx_queue_info *q);
|
||||
int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
@@ -986,32 +986,6 @@ int ath_tx_get_qnum(struct ath_softc *sc
|
||||
return qnum;
|
||||
}
|
||||
|
||||
-struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb)
|
||||
-{
|
||||
- struct ath_txq *txq = NULL;
|
||||
- u16 skb_queue = skb_get_queue_mapping(skb);
|
||||
- int qnum;
|
||||
-
|
||||
- qnum = ath_get_hal_qnum(skb_queue, sc);
|
||||
- txq = &sc->tx.txq[qnum];
|
||||
-
|
||||
- spin_lock_bh(&txq->axq_lock);
|
||||
-
|
||||
- if (txq->axq_depth >= (ATH_TXBUF - 20)) {
|
||||
- ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_XMIT,
|
||||
- "TX queue: %d is full, depth: %d\n",
|
||||
- qnum, txq->axq_depth);
|
||||
- ath_mac80211_stop_queue(sc, skb_queue);
|
||||
- txq->stopped = 1;
|
||||
- spin_unlock_bh(&txq->axq_lock);
|
||||
- return NULL;
|
||||
- }
|
||||
-
|
||||
- spin_unlock_bh(&txq->axq_lock);
|
||||
-
|
||||
- return txq;
|
||||
-}
|
||||
-
|
||||
int ath_txq_update(struct ath_softc *sc, int qnum,
|
||||
struct ath9k_tx_queue_info *qinfo)
|
||||
{
|
||||
@@ -1811,6 +1785,7 @@ int ath_tx_start(struct ieee80211_hw *hw
|
||||
struct ath_wiphy *aphy = hw->priv;
|
||||
struct ath_softc *sc = aphy->sc;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
+ struct ath_txq *txq = txctl->txq;
|
||||
struct ath_buf *bf;
|
||||
int r;
|
||||
|
||||
@@ -1820,10 +1795,16 @@ int ath_tx_start(struct ieee80211_hw *hw
|
||||
return -1;
|
||||
}
|
||||
|
||||
+ bf->txq = txctl->txq;
|
||||
+ spin_lock_bh(&bf->txq->axq_lock);
|
||||
+ if (++bf->txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) {
|
||||
+ ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb));
|
||||
+ txq->stopped = 1;
|
||||
+ }
|
||||
+ spin_unlock_bh(&bf->txq->axq_lock);
|
||||
+
|
||||
r = ath_tx_setup_buffer(hw, bf, skb, txctl);
|
||||
if (unlikely(r)) {
|
||||
- struct ath_txq *txq = txctl->txq;
|
||||
-
|
||||
ath_print(common, ATH_DBG_FATAL, "TX mem alloc failure\n");
|
||||
|
||||
/* upon ath_tx_processq() this TX queue will be resumed, we
|
||||
@@ -1831,7 +1812,7 @@ int ath_tx_start(struct ieee80211_hw *hw
|
||||
* we will at least have to run TX completionon one buffer
|
||||
* on the queue */
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
- if (sc->tx.txq[txq->axq_qnum].axq_depth > 1) {
|
||||
+ if (!txq->stopped && txq->axq_depth > 1) {
|
||||
ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb));
|
||||
txq->stopped = 1;
|
||||
}
|
||||
@@ -1972,6 +1953,13 @@ static void ath_tx_complete_buf(struct a
|
||||
tx_flags |= ATH_TX_XRETRY;
|
||||
}
|
||||
|
||||
+ if (bf->txq) {
|
||||
+ spin_lock_bh(&bf->txq->axq_lock);
|
||||
+ bf->txq->pending_frames--;
|
||||
+ spin_unlock_bh(&bf->txq->axq_lock);
|
||||
+ bf->txq = NULL;
|
||||
+ }
|
||||
+
|
||||
dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE);
|
||||
ath_tx_complete(sc, skb, bf->aphy, tx_flags);
|
||||
ath_debug_stat_tx(sc, txq, bf, ts);
|
||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -1026,6 +1026,7 @@ static int ath9k_tx(struct ieee80211_hw
|
||||
struct ath_tx_control txctl;
|
||||
int padpos, padsize;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
+ int qnum;
|
||||
|
||||
if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) {
|
||||
ath_print(common, ATH_DBG_XMIT,
|
||||
@@ -1098,11 +1099,8 @@ static int ath9k_tx(struct ieee80211_hw
|
||||
memmove(skb->data, skb->data + padsize, padpos);
|
||||
}
|
||||
|
||||
- /* Check if a tx queue is available */
|
||||
-
|
||||
- txctl.txq = ath_test_get_txq(sc, skb);
|
||||
- if (!txctl.txq)
|
||||
- goto exit;
|
||||
+ qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc);
|
||||
+ txctl.txq = &sc->tx.txq[qnum];
|
||||
|
||||
ath_print(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb);
|
||||
|
Loading…
Reference in New Issue