Linux wireless drivers development
 help / color / mirror / Atom feed
From: Felix Fietkau <nbd@openwrt.org>
To: linux-wireless@vger.kernel.org
Cc: linville@tuxdriver.com, sujith@msujith.org
Subject: [PATCH v2 11/12] ath9k: improve tx scheduling fairness
Date: Tue,  6 Aug 2013 14:18:12 +0200	[thread overview]
Message-ID: <1375791493-83971-11-git-send-email-nbd@openwrt.org> (raw)
In-Reply-To: <1375791493-83971-1-git-send-email-nbd@openwrt.org>

Instead of trying to schedule the same TID multiple times in a loop,
iterate over other TIDs/stations first.

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
---
 drivers/net/wireless/ath/ath9k/xmit.c | 89 ++++++++++++++++++++---------------
 1 file changed, 50 insertions(+), 39 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 3b66f2b..f9e6eb2 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1345,8 +1345,8 @@ ath_tx_form_burst(struct ath_softc *sc, struct ath_txq *txq,
 	} while (1);
 }
 
-static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
-			      struct ath_atx_tid *tid)
+static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
+			      struct ath_atx_tid *tid, bool *stop)
 {
 	struct ath_buf *bf;
 	struct ieee80211_tx_info *tx_info;
@@ -1355,40 +1355,41 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
 	int aggr_len = 0;
 	bool aggr, last = true;
 
-	do {
-		if (!ath_tid_has_buffered(tid))
-			return;
+	if (!ath_tid_has_buffered(tid))
+		return false;
 
-		INIT_LIST_HEAD(&bf_q);
+	INIT_LIST_HEAD(&bf_q);
 
-		bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q);
-		if (!bf)
-			break;
+	bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q);
+	if (!bf)
+		return false;
 
-		tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
-		aggr = !!(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
-		if ((aggr && txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) ||
-		    (!aggr && txq->axq_depth >= ATH_NON_AGGR_MIN_QDEPTH))
-			break;
+	tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
+	aggr = !!(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
+	if ((aggr && txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) ||
+		(!aggr && txq->axq_depth >= ATH_NON_AGGR_MIN_QDEPTH)) {
+		*stop = true;
+		return false;
+	}
 
-		ath_set_rates(tid->an->vif, tid->an->sta, bf);
-		if (aggr)
-			last = ath_tx_form_aggr(sc, txq, tid, &bf_q, bf,
-						tid_q, &aggr_len);
-		else
-			ath_tx_form_burst(sc, txq, tid, &bf_q, bf, tid_q);
+	ath_set_rates(tid->an->vif, tid->an->sta, bf);
+	if (aggr)
+		last = ath_tx_form_aggr(sc, txq, tid, &bf_q, bf,
+					tid_q, &aggr_len);
+	else
+		ath_tx_form_burst(sc, txq, tid, &bf_q, bf, tid_q);
 
-		if (list_empty(&bf_q))
-			return;
+	if (list_empty(&bf_q))
+		return false;
 
-		if (tid->ac->clear_ps_filter) {
-			tid->ac->clear_ps_filter = false;
-			tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
-		}
+	if (tid->ac->clear_ps_filter) {
+		tid->ac->clear_ps_filter = false;
+		tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
+	}
 
-		ath_tx_fill_desc(sc, bf, txq, aggr_len);
-		ath_tx_txqaddbuf(sc, txq, &bf_q, false);
-	} while (!last);
+	ath_tx_fill_desc(sc, bf, txq, aggr_len);
+	ath_tx_txqaddbuf(sc, txq, &bf_q, false);
+	return true;
 }
 
 int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
@@ -1824,25 +1825,27 @@ void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq)
  */
 void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
 {
-	struct ath_atx_ac *ac, *ac_tmp, *last_ac;
+	struct ath_atx_ac *ac, *last_ac;
 	struct ath_atx_tid *tid, *last_tid;
+	bool sent = false;
 
 	if (test_bit(SC_OP_HW_RESET, &sc->sc_flags) ||
-	    list_empty(&txq->axq_acq) ||
-	    txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
+	    list_empty(&txq->axq_acq))
 		return;
 
 	rcu_read_lock();
 
-	ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list);
 	last_ac = list_entry(txq->axq_acq.prev, struct ath_atx_ac, list);
+	while (!list_empty(&txq->axq_acq)) {
+		bool stop = false;
 
-	list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) {
+		ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list);
 		last_tid = list_entry(ac->tid_q.prev, struct ath_atx_tid, list);
 		list_del(&ac->list);
 		ac->sched = false;
 
 		while (!list_empty(&ac->tid_q)) {
+
 			tid = list_first_entry(&ac->tid_q, struct ath_atx_tid,
 					       list);
 			list_del(&tid->list);
@@ -1851,7 +1854,8 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
 			if (tid->paused)
 				continue;
 
-			ath_tx_sched_aggr(sc, txq, tid);
+			if (ath_tx_sched_aggr(sc, txq, tid, &stop))
+				sent = true;
 
 			/*
 			 * add tid to round-robin queue if more frames
@@ -1860,8 +1864,7 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
 			if (ath_tid_has_buffered(tid))
 				ath_tx_queue_tid(txq, tid);
 
-			if (tid == last_tid ||
-			    txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
+			if (stop || tid == last_tid)
 				break;
 		}
 
@@ -1870,9 +1873,17 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
 			list_add_tail(&ac->list, &txq->axq_acq);
 		}
 
-		if (ac == last_ac ||
-		    txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
+		if (stop)
 			break;
+
+		if (ac == last_ac) {
+			if (!sent)
+				break;
+
+			sent = false;
+			last_ac = list_entry(txq->axq_acq.prev,
+					     struct ath_atx_ac, list);
+		}
 	}
 
 	rcu_read_unlock();
-- 
1.8.0.2


  parent reply	other threads:[~2013-08-06 12:18 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-08-06 12:18 [PATCH v2 01/12] ath9k: add utility functions for accessing tid queues Felix Fietkau
2013-08-06 12:18 ` [PATCH v2 02/12] ath9k: split tid retry packets into a separate queue Felix Fietkau
2013-08-06 12:18 ` [PATCH v2 03/12] ath9k: add function for getting the tx tid for a packet Felix Fietkau
2013-08-06 12:18 ` [PATCH v2 04/12] ath9k: add CAB queue info to debugfs Felix Fietkau
2013-08-06 12:18 ` [PATCH v2 05/12] ath9k: simplify ath_tx_form_aggr Felix Fietkau
2013-08-06 12:18 ` [PATCH v2 06/12] ath9k: fix block ack window tracking check Felix Fietkau
2013-08-06 12:18 ` [PATCH v2 07/12] ath9k: prepare queueing code for handling unaggregated traffic Felix Fietkau
2013-08-06 12:18 ` [PATCH v2 08/12] ath9k: fix clearing expired A-MPDU subframes in tx completion Felix Fietkau
2013-08-06 12:18 ` [PATCH v2 09/12] ath9k: always clear ps filter bit on new assoc Felix Fietkau
2013-08-06 12:18 ` [PATCH v2 10/12] ath9k: use software queues for un-aggregated data packets Felix Fietkau
2013-08-06 12:18 ` Felix Fietkau [this message]
2013-08-06 12:18 ` [PATCH v2 12/12] ath9k: use software queueing for multicast traffic Felix Fietkau

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1375791493-83971-11-git-send-email-nbd@openwrt.org \
    --to=nbd@openwrt.org \
    --cc=linux-wireless@vger.kernel.org \
    --cc=linville@tuxdriver.com \
    --cc=sujith@msujith.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox