svn commit: r245708 - head/sys/dev/ath
Adrian Chadd
adrian at FreeBSD.org
Mon Jan 21 04:06:05 UTC 2013
Author: adrian
Date: Mon Jan 21 04:06:04 2013
New Revision: 245708
URL: http://svnweb.freebsd.org/changeset/base/245708
Log:
Migrate CLRDMASK to be a per-node flag, rather than a per-TID flag.
This is easily possible now that the TX is protected by a single
lock, rather than a per-TXQ (and thus per-TID) lock.
Only set CLRDMASK if none of the destinations are filtered.
This likely will need some tuning when it comes time to do UASPD/PS-POLL
TX, however at that point it should be manually set anyway.
Tested:
* AR9280, STA mode
TODO:
* More thorough testing in AP mode
* test other chipsets, just to be safe/sure.
Modified:
head/sys/dev/ath/if_ath_tx.c
head/sys/dev/ath/if_athvar.h
Modified: head/sys/dev/ath/if_ath_tx.c
==============================================================================
--- head/sys/dev/ath/if_ath_tx.c Mon Jan 21 02:47:14 2013 (r245707)
+++ head/sys/dev/ath/if_ath_tx.c Mon Jan 21 04:06:04 2013 (r245708)
@@ -1397,12 +1397,13 @@ static void
ath_tx_update_clrdmask(struct ath_softc *sc, struct ath_tid *tid,
struct ath_buf *bf)
{
+ struct ath_node *an = ATH_NODE(bf->bf_node);
ATH_TX_LOCK_ASSERT(sc);
- if (tid->clrdmask == 1) {
+ if (an->clrdmask == 1) {
bf->bf_state.bfs_txflags |= HAL_TXDESC_CLRDMASK;
- tid->clrdmask = 0;
+ an->clrdmask = 0;
}
}
@@ -2888,6 +2889,29 @@ ath_tx_swq(struct ath_softc *sc, struct
}
/*
+ * Only set the clrdmask bit if none of the nodes are currently
+ * filtered.
+ *
+ * XXX TODO: go through all the callers and check to see
+ * which are being called in the context of looping over all
+ * TIDs (eg, if all tids are being paused, resumed, etc.)
+ * That'll avoid O(n^2) complexity here.
+ */
+static void
+ath_tx_set_clrdmask(struct ath_softc *sc, struct ath_node *an)
+{
+ int i;
+
+ ATH_TX_LOCK_ASSERT(sc);
+
+ for (i = 0; i < IEEE80211_TID_SIZE; i++) {
+ if (an->an_tid[i].isfiltered == 1)
+ break;
+ }
+ an->clrdmask = 1;
+}
+
+/*
* Configure the per-TID node state.
*
* This likely belongs in if_ath_node.c but I can't think of anywhere
@@ -2918,12 +2942,12 @@ ath_tx_tid_init(struct ath_softc *sc, st
atid->sched = 0;
atid->hwq_depth = 0;
atid->cleanup_inprogress = 0;
- atid->clrdmask = 1; /* Always start by setting this bit */
if (i == IEEE80211_NONQOS_TID)
atid->ac = ATH_NONQOS_TID_AC;
else
atid->ac = TID_TO_WME_AC(i);
}
+ an->clrdmask = 1; /* Always start by setting this bit */
}
/*
@@ -2949,7 +2973,6 @@ ath_tx_tid_pause(struct ath_softc *sc, s
static void
ath_tx_tid_resume(struct ath_softc *sc, struct ath_tid *tid)
{
-
ATH_TX_LOCK_ASSERT(sc);
tid->paused--;
@@ -2964,7 +2987,7 @@ ath_tx_tid_resume(struct ath_softc *sc,
* Override the clrdmask configuration for the next frame
* from this TID, just to get the ball rolling.
*/
- tid->clrdmask = 1;
+ ath_tx_set_clrdmask(sc, tid->an);
if (tid->axq_depth == 0)
return;
@@ -3047,7 +3070,8 @@ ath_tx_tid_filt_comp_complete(struct ath
DPRINTF(sc, ATH_DEBUG_SW_TX_FILT, "%s: hwq=0, transition back\n",
__func__);
tid->isfiltered = 0;
- tid->clrdmask = 1;
+ /* XXX ath_tx_tid_resume() also calls ath_tx_set_clrdmask()! */
+ ath_tx_set_clrdmask(sc, tid->an);
/* XXX this is really quite inefficient */
while ((bf = ATH_TID_FILT_LAST(tid, ath_bufhead_s)) != NULL) {
@@ -3303,7 +3327,7 @@ ath_tx_tid_bar_tx(struct ath_softc *sc,
* Override the clrdmask configuration for the next frame,
* just to get the ball rolling.
*/
- tid->clrdmask = 1;
+ ath_tx_set_clrdmask(sc, tid->an);
/*
* Calculate new BAW left edge, now that all frames have either
@@ -3484,7 +3508,7 @@ ath_tx_tid_drain(struct ath_softc *sc, s
*
* This won't hurt things if the TID is about to be freed.
*/
- tid->clrdmask = 1;
+ ath_tx_set_clrdmask(sc, tid->an);
/*
* Now that it's completed, grab the TID lock and update
Modified: head/sys/dev/ath/if_athvar.h
==============================================================================
--- head/sys/dev/ath/if_athvar.h Mon Jan 21 02:47:14 2013 (r245707)
+++ head/sys/dev/ath/if_athvar.h Mon Jan 21 04:06:04 2013 (r245708)
@@ -132,7 +132,6 @@ struct ath_tid {
int bar_wait; /* waiting for BAR */
int bar_tx; /* BAR TXed */
int isfiltered; /* is this node currently filtered */
- int clrdmask; /* has clrdmask been set */
/*
* Is the TID being cleaned up after a transition
@@ -182,6 +181,7 @@ struct ath_node {
struct mtx an_mtx; /* protecting the ath_node state */
uint32_t an_swq_depth; /* how many SWQ packets for this
node */
+ int clrdmask; /* has clrdmask been set */
/* variable-length rate control state follows */
};
#define ATH_NODE(ni) ((struct ath_node *)(ni))
More information about the svn-src-head
mailing list