svn commit: r250606 - head/sys/dev/ath

Adrian Chadd adrian at FreeBSD.org
Mon May 13 18:56:05 UTC 2013


Author: adrian
Date: Mon May 13 18:56:04 2013
New Revision: 250606
URL: http://svnweb.freebsd.org/changeset/base/250606

Log:
  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.

Modified:
  head/sys/dev/ath/if_ath.c

Modified: head/sys/dev/ath/if_ath.c
==============================================================================
--- head/sys/dev/ath/if_ath.c	Mon May 13 18:34:33 2013	(r250605)
+++ head/sys/dev/ath/if_ath.c	Mon May 13 18:56:04 2013	(r250606)
@@ -3845,8 +3845,11 @@ ath_tx_default_comp(struct ath_softc *sc
 	 * 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, 
 	    (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 *
 	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 *
 	 * 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 *
 		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 *
 		    "%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 *
 		    "%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 *
 		 * 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, 
 	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, 
 		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, 
 			    "%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, 
 		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, 
 			    " 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


More information about the svn-src-all mailing list