summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authoradrian <adrian@FreeBSD.org>2013-05-13 18:56:04 +0000
committeradrian <adrian@FreeBSD.org>2013-05-13 18:56:04 +0000
commit4bd9be4c73c9f85431d06909d7dfc0bbffed8ffa (patch)
treeba63759b23784cc27963f0fd621aed23f805efcb /sys/dev
parent99aa6ad820a960dd26eeafaa6bff9f2a77da489d (diff)
downloadFreeBSD-src-4bd9be4c73c9f85431d06909d7dfc0bbffed8ffa.zip
FreeBSD-src-4bd9be4c73c9f85431d06909d7dfc0bbffed8ffa.tar.gz
Begin tidying up the reassociation and node sleep/wakeup paths.
* Move the node sleep/wake state under the TX lock rather than the node lock. Let's leave the node lock protecting rate control only for now. * When reassociating, various state needs to be cleared. For example, the aggregate session needs to be torn down, including any pending aggregation negotiation and BAR TX waiting. * .. and we need to do a "cleanup" pass since frames in the hardware TX queue need to be transmitted. Modify ath_tx_tid_cleanup() to be called with the TX lock held and push frames into a completion list. This allows for the cleanup to be done atomically for all TIDs in a node rather than grabbing and releasing the TX lock each time.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ath/if_ath.c59
1 files changed, 37 insertions, 22 deletions
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c
index 5331fd0..4416256 100644
--- a/sys/dev/ath/if_ath.c
+++ b/sys/dev/ath/if_ath.c
@@ -3845,8 +3845,11 @@ ath_tx_default_comp(struct ath_softc *sc, struct ath_buf *bf, int fail)
* XXX TODO: during drain, ensure that the callback is
* being called so we get a chance to update the TIM.
*/
- if (bf->bf_node)
+ if (bf->bf_node) {
+ ATH_TX_LOCK(sc);
ath_tx_update_tim(sc, bf->bf_node, 0);
+ ATH_TX_UNLOCK(sc);
+ }
/*
* Do any tx complete callback. Note this must
@@ -5380,6 +5383,31 @@ ath_newassoc(struct ieee80211_node *ni, int isnew)
(vap->iv_flags & IEEE80211_F_PRIVACY) == 0 && sc->sc_hasclrkey &&
ni->ni_ucastkey.wk_keyix == IEEE80211_KEYIX_NONE)
ath_setup_stationkey(ni);
+
+ /*
+ * If we're reassociating, make sure that any paused queues
+ * get unpaused.
+ *
+ * Now, we may hvae frames in the hardware queue for this node.
+ * So if we are reassociating and there are frames in the queue,
+ * we need to go through the cleanup path to ensure that they're
+ * marked as non-aggregate.
+ */
+ if (! isnew) {
+ device_printf(sc->sc_dev,
+ "%s: %6D: reassoc; is_powersave=%d\n",
+ __func__,
+ ni->ni_macaddr,
+ ":",
+ an->an_is_powersave);
+
+ /* XXX for now, we can't hold the lock across assoc */
+ ath_tx_node_reassoc(sc, an);
+
+ /* XXX for now, we can't hold the lock across wakeup */
+ if (an->an_is_powersave)
+ ath_tx_node_wakeup(sc, an);
+ }
}
static int
@@ -5959,12 +5987,7 @@ ath_node_set_tim(struct ieee80211_node *ni, int enable)
struct ath_vap *avp = ATH_VAP(ni->ni_vap);
int changed = 0;
- ATH_NODE_UNLOCK_ASSERT(an);
-
- /*
- * For now, just track and then update the TIM.
- */
- ATH_NODE_LOCK(an);
+ ATH_TX_LOCK(sc);
an->an_stack_psq = enable;
/*
@@ -5975,7 +5998,7 @@ ath_node_set_tim(struct ieee80211_node *ni, int enable)
* and AP/IBSS node power save.
*/
if (avp->av_set_tim == NULL) {
- ATH_NODE_UNLOCK(an);
+ ATH_TX_UNLOCK(sc);
return (0);
}
@@ -5997,13 +6020,13 @@ ath_node_set_tim(struct ieee80211_node *ni, int enable)
DPRINTF(sc, ATH_DEBUG_NODE_PWRSAVE,
"%s: an=%p, enable=%d, tim_set=1, ignoring\n",
__func__, an, enable);
- ATH_NODE_UNLOCK(an);
+ ATH_TX_UNLOCK(sc);
} else if (enable) {
DPRINTF(sc, ATH_DEBUG_NODE_PWRSAVE,
"%s: an=%p, enable=%d, enabling TIM\n",
__func__, an, enable);
an->an_tim_set = 1;
- ATH_NODE_UNLOCK(an);
+ ATH_TX_UNLOCK(sc);
changed = avp->av_set_tim(ni, enable);
} else if (atomic_load_acq_int(&an->an_swq_depth) == 0) {
/* disable */
@@ -6011,7 +6034,7 @@ ath_node_set_tim(struct ieee80211_node *ni, int enable)
"%s: an=%p, enable=%d, an_swq_depth == 0, disabling\n",
__func__, an, enable);
an->an_tim_set = 0;
- ATH_NODE_UNLOCK(an);
+ ATH_TX_UNLOCK(sc);
changed = avp->av_set_tim(ni, enable);
} else if (! an->an_is_powersave) {
/*
@@ -6021,7 +6044,7 @@ ath_node_set_tim(struct ieee80211_node *ni, int enable)
"%s: an=%p, enable=%d, an_pwrsave=0, disabling\n",
__func__, an, enable);
an->an_tim_set = 0;
- ATH_NODE_UNLOCK(an);
+ ATH_TX_UNLOCK(sc);
changed = avp->av_set_tim(ni, enable);
} else {
/*
@@ -6029,7 +6052,7 @@ ath_node_set_tim(struct ieee80211_node *ni, int enable)
* software queue isn't empty, so don't clear the TIM bit
* for now.
*/
- ATH_NODE_UNLOCK(an);
+ ATH_TX_UNLOCK(sc);
DPRINTF(sc, ATH_DEBUG_NODE_PWRSAVE,
"%s: enable=%d, an_swq_depth > 0, ignoring\n",
__func__, enable);
@@ -6094,7 +6117,7 @@ ath_tx_update_tim(struct ath_softc *sc, struct ieee80211_node *ni,
if (avp->av_set_tim == NULL)
return;
- ATH_NODE_UNLOCK_ASSERT(an);
+ ATH_TX_LOCK_ASSERT(sc);
if (enable) {
/*
@@ -6104,7 +6127,6 @@ ath_tx_update_tim(struct ath_softc *sc, struct ieee80211_node *ni,
if (atomic_load_acq_int(&an->an_swq_depth) == 0)
return;
- ATH_NODE_LOCK(an);
if (an->an_is_powersave &&
an->an_tim_set == 0 &&
atomic_load_acq_int(&an->an_swq_depth) != 0) {
@@ -6112,10 +6134,7 @@ ath_tx_update_tim(struct ath_softc *sc, struct ieee80211_node *ni,
"%s: an=%p, swq_depth>0, tim_set=0, set!\n",
__func__, an);
an->an_tim_set = 1;
- ATH_NODE_UNLOCK(an);
(void) avp->av_set_tim(ni, 1);
- } else {
- ATH_NODE_UNLOCK(an);
}
} else {
/*
@@ -6124,7 +6143,6 @@ ath_tx_update_tim(struct ath_softc *sc, struct ieee80211_node *ni,
if (atomic_load_acq_int(&an->an_swq_depth) != 0)
return;
- ATH_NODE_LOCK(an);
if (an->an_is_powersave &&
an->an_stack_psq == 0 &&
an->an_tim_set == 1 &&
@@ -6134,10 +6152,7 @@ ath_tx_update_tim(struct ath_softc *sc, struct ieee80211_node *ni,
" clear!\n",
__func__, an);
an->an_tim_set = 0;
- ATH_NODE_UNLOCK(an);
(void) avp->av_set_tim(ni, 0);
- } else {
- ATH_NODE_UNLOCK(an);
}
}
#else
OpenPOWER on IntegriCloud