diff options
author | adrian <adrian@FreeBSD.org> | 2013-05-13 18:56:04 +0000 |
---|---|---|
committer | adrian <adrian@FreeBSD.org> | 2013-05-13 18:56:04 +0000 |
commit | 4bd9be4c73c9f85431d06909d7dfc0bbffed8ffa (patch) | |
tree | ba63759b23784cc27963f0fd621aed23f805efcb /sys/dev | |
parent | 99aa6ad820a960dd26eeafaa6bff9f2a77da489d (diff) | |
download | FreeBSD-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.c | 59 |
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 |