diff options
author | Felix Fietkau <nbd@openwrt.org> | 2010-12-16 18:57:00 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-12-20 14:49:48 -0500 |
commit | 4b3ba66a47311770b21e7aba481f4f2a90ba3084 (patch) | |
tree | c4dc1302ff9c641cfcd6173232bcbe925a64abce /drivers | |
parent | 5c405b5c3e435fd332058c59ee58eaa1ac9c513a (diff) |
ath9k: fix queue depth check for forming new aggregates
To improve aggregation length, there should not be more than two fully formed
A-MPDU frames in the hardware queue. To ensure this, the code checks the tx
queue length before forming new A-MPDUs. This can reduce the throughput (or
maybe even starve out A-MPDU traffic) when too many non-aggregated frames are
in the queue.
Fix this by keeping track of pending A-MPDU frames (even when they're sent out
as single frames), but exclude rate control probing frames to improve
performance.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ath9k.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/xmit.c | 21 |
2 files changed, 19 insertions, 3 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index b0b1216dae0a..9fd95191eebc 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -189,6 +189,7 @@ struct ath_txq { | |||
189 | struct list_head axq_q; | 189 | struct list_head axq_q; |
190 | spinlock_t axq_lock; | 190 | spinlock_t axq_lock; |
191 | u32 axq_depth; | 191 | u32 axq_depth; |
192 | u32 axq_ampdu_depth; | ||
192 | bool stopped; | 193 | bool stopped; |
193 | bool axq_tx_inprogress; | 194 | bool axq_tx_inprogress; |
194 | struct list_head axq_acq; | 195 | struct list_head axq_acq; |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 966236953e77..332d1feb5c18 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -838,7 +838,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
838 | ath_tx_txqaddbuf(sc, txq, &bf_q); | 838 | ath_tx_txqaddbuf(sc, txq, &bf_q); |
839 | TX_STAT_INC(txq->axq_qnum, a_aggr); | 839 | TX_STAT_INC(txq->axq_qnum, a_aggr); |
840 | 840 | ||
841 | } while (txq->axq_depth < ATH_AGGR_MIN_QDEPTH && | 841 | } while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH && |
842 | status != ATH_AGGR_BAW_CLOSED); | 842 | status != ATH_AGGR_BAW_CLOSED); |
843 | } | 843 | } |
844 | 844 | ||
@@ -999,6 +999,7 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) | |||
999 | INIT_LIST_HEAD(&txq->axq_acq); | 999 | INIT_LIST_HEAD(&txq->axq_acq); |
1000 | spin_lock_init(&txq->axq_lock); | 1000 | spin_lock_init(&txq->axq_lock); |
1001 | txq->axq_depth = 0; | 1001 | txq->axq_depth = 0; |
1002 | txq->axq_ampdu_depth = 0; | ||
1002 | txq->axq_tx_inprogress = false; | 1003 | txq->axq_tx_inprogress = false; |
1003 | sc->tx.txqsetup |= 1<<qnum; | 1004 | sc->tx.txqsetup |= 1<<qnum; |
1004 | 1005 | ||
@@ -1068,6 +1069,12 @@ int ath_cabq_update(struct ath_softc *sc) | |||
1068 | return 0; | 1069 | return 0; |
1069 | } | 1070 | } |
1070 | 1071 | ||
1072 | static bool bf_is_ampdu_not_probing(struct ath_buf *bf) | ||
1073 | { | ||
1074 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(bf->bf_mpdu); | ||
1075 | return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE); | ||
1076 | } | ||
1077 | |||
1071 | /* | 1078 | /* |
1072 | * Drain a given TX queue (could be Beacon or Data) | 1079 | * Drain a given TX queue (could be Beacon or Data) |
1073 | * | 1080 | * |
@@ -1126,7 +1133,8 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) | |||
1126 | } | 1133 | } |
1127 | 1134 | ||
1128 | txq->axq_depth--; | 1135 | txq->axq_depth--; |
1129 | 1136 | if (bf_is_ampdu_not_probing(bf)) | |
1137 | txq->axq_ampdu_depth--; | ||
1130 | spin_unlock_bh(&txq->axq_lock); | 1138 | spin_unlock_bh(&txq->axq_lock); |
1131 | 1139 | ||
1132 | if (bf_isampdu(bf)) | 1140 | if (bf_isampdu(bf)) |
@@ -1316,6 +1324,8 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, | |||
1316 | ath9k_hw_txstart(ah, txq->axq_qnum); | 1324 | ath9k_hw_txstart(ah, txq->axq_qnum); |
1317 | } | 1325 | } |
1318 | txq->axq_depth++; | 1326 | txq->axq_depth++; |
1327 | if (bf_is_ampdu_not_probing(bf)) | ||
1328 | txq->axq_ampdu_depth++; | ||
1319 | } | 1329 | } |
1320 | 1330 | ||
1321 | static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, | 1331 | static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, |
@@ -1336,7 +1346,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
1336 | */ | 1346 | */ |
1337 | if (!list_empty(&tid->buf_q) || tid->paused || | 1347 | if (!list_empty(&tid->buf_q) || tid->paused || |
1338 | !BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno) || | 1348 | !BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno) || |
1339 | txctl->txq->axq_depth >= ATH_AGGR_MIN_QDEPTH) { | 1349 | txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) { |
1340 | /* | 1350 | /* |
1341 | * Add this frame to software queue for scheduling later | 1351 | * Add this frame to software queue for scheduling later |
1342 | * for aggregation. | 1352 | * for aggregation. |
@@ -2040,6 +2050,9 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2040 | txq->axq_tx_inprogress = false; | 2050 | txq->axq_tx_inprogress = false; |
2041 | if (bf_held) | 2051 | if (bf_held) |
2042 | list_del(&bf_held->list); | 2052 | list_del(&bf_held->list); |
2053 | |||
2054 | if (bf_is_ampdu_not_probing(bf)) | ||
2055 | txq->axq_ampdu_depth--; | ||
2043 | spin_unlock_bh(&txq->axq_lock); | 2056 | spin_unlock_bh(&txq->axq_lock); |
2044 | 2057 | ||
2045 | if (bf_held) | 2058 | if (bf_held) |
@@ -2168,6 +2181,8 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) | |||
2168 | INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH); | 2181 | INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH); |
2169 | txq->axq_depth--; | 2182 | txq->axq_depth--; |
2170 | txq->axq_tx_inprogress = false; | 2183 | txq->axq_tx_inprogress = false; |
2184 | if (bf_is_ampdu_not_probing(bf)) | ||
2185 | txq->axq_ampdu_depth--; | ||
2171 | spin_unlock_bh(&txq->axq_lock); | 2186 | spin_unlock_bh(&txq->axq_lock); |
2172 | 2187 | ||
2173 | txok = !(txs.ts_status & ATH9K_TXERR_MASK); | 2188 | txok = !(txs.ts_status & ATH9K_TXERR_MASK); |