Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 20 Sep 2012 03:13:20 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r240724 - head/sys/dev/ath
Message-ID:  <201209200313.q8K3DKlO028959@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: adrian
Date: Thu Sep 20 03:13:20 2012
New Revision: 240724
URL: http://svn.freebsd.org/changeset/base/240724

Log:
  Introduce the CLRDMASK gating based on tid->clrdmask, enabling filtered
  frames to occur.
  
  * Create a new function which will set the bf_flags CLRDMASK bit
    if required.
  * For raw frames, always set CLRDMASK.
  * For BAR, ADDBA frames, always set CLRDMASK.
  * For everything else, check if CLRDMASK needs to be set before
    calling tx_setds() or tx_setds11n().
  * When unpausing a queue or drain/resetting it, set tid->clrdmask=1
    just to ensure traffic starts flowing.
  
  What I need to do:
  
  * Modify that function to _clear_ the CLRDMASK if it's not required,
    or retried frames may have CLRDMASK set when they don't need to.
    (Which isn't a huge deal, but..)
  
  Whilst I'm here:
  
  * ath_tx_normal_xmit() should really act like the AMPDU session TX
    functions - any incomplete frames will end up being assigned
    ath_tx_normal_comp() which will decrement tid->hwq_depth - but that
    won't have been incremented.
  
    So whilst I'm here, add a comment to do that.
  
  * Fix the debug print function to be slightly clearer about things;
    it's not a good sign when I can't interpret my own debugging output.
  
  I've done some testing on AR9280/AR5416/AR9160 STA and AP modes.

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

Modified: head/sys/dev/ath/if_ath_tx.c
==============================================================================
--- head/sys/dev/ath/if_ath_tx.c	Thu Sep 20 03:09:58 2012	(r240723)
+++ head/sys/dev/ath/if_ath_tx.c	Thu Sep 20 03:13:20 2012	(r240724)
@@ -1285,6 +1285,9 @@ ath_tx_xmit_normal(struct ath_softc *sc,
 	ath_tx_rate_fill_rcflags(sc, bf);
 	ath_tx_setds(sc, bf);
 
+	/* XXX Bump TID HWQ counter */
+	/* XXX Assign a completion handler */
+
 	/* Hand off to hardware */
 	ath_tx_handoff(sc, txq, bf);
 }
@@ -1384,7 +1387,8 @@ ath_tx_normal_setup(struct ath_softc *sc
 	}
 
 	an = ATH_NODE(ni);
-	flags = HAL_TXDESC_CLRDMASK;		/* XXX needed for crypto errs */
+	//flags = HAL_TXDESC_CLRDMASK;		/* XXX needed for crypto errs */
+	flags = 0;
 	ismrr = 0;				/* default no multi-rate retry*/
 	pri = M_WME_GETAC(m0);			/* honor classification */
 	/* XXX use txparams instead of fixed values */
@@ -1598,12 +1602,15 @@ ath_tx_normal_setup(struct ath_softc *sc
 }
 
 /*
- * Direct-dispatch the current frame to the hardware.
+ * Queue a frame to the hardware or software queue.
  *
  * This can be called by the net80211 code.
  *
  * XXX what about locking? Or, push the seqno assign into the
  * XXX aggregate scheduler so its serialised?
+ *
+ * XXX When sending management frames via ath_raw_xmit(),
+ *     should CLRDMASK be set unconditionally?
  */
 int
 ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni,
@@ -1774,11 +1781,13 @@ ath_tx_start(struct ath_softc *sc, struc
 	if (txq == &avp->av_mcastq) {
 		DPRINTF(sc, ATH_DEBUG_SW_TX,
 		    "%s: bf=%p: mcastq: TX'ing\n", __func__, bf);
+		bf->bf_state.bfs_txflags |= HAL_TXDESC_CLRDMASK;
 		ath_tx_xmit_normal(sc, txq, bf);
 	} else if (type == IEEE80211_FC0_TYPE_CTL &&
 		    subtype == IEEE80211_FC0_SUBTYPE_BAR) {
 		DPRINTF(sc, ATH_DEBUG_SW_TX,
 		    "%s: BAR: TX'ing direct\n", __func__);
+		bf->bf_state.bfs_txflags |= HAL_TXDESC_CLRDMASK;
 		ath_tx_xmit_normal(sc, txq, bf);
 	} else {
 		/* add to software queue */
@@ -1791,6 +1800,7 @@ ath_tx_start(struct ath_softc *sc, struc
 	 * For now, since there's no software queue,
 	 * direct-dispatch to the hardware.
 	 */
+	bf->bf_state.bfs_txflags |= HAL_TXDESC_CLRDMASK;
 	ath_tx_xmit_normal(sc, txq, bf);
 #endif
 done:
@@ -1874,6 +1884,7 @@ ath_tx_raw_start(struct ath_softc *sc, s
 	wh = mtod(m0, struct ieee80211_frame *);
 	bf->bf_node = ni;			/* NB: held reference */
 
+	/* Always enable CLRDMASK for raw frames for now.. */
 	flags = HAL_TXDESC_CLRDMASK;		/* XXX needed for crypto errs */
 	flags |= HAL_TXDESC_INTREQ;		/* force interrupt */
 	if (params->ibp_flags & IEEE80211_BPF_RTS)
@@ -2002,6 +2013,7 @@ ath_tx_raw_start(struct ath_softc *sc, s
 	    __func__, do_override);
 
 	if (do_override) {
+		bf->bf_state.bfs_txflags |= HAL_TXDESC_CLRDMASK;
 		ath_tx_xmit_normal(sc, sc->sc_ac2q[pri], bf);
 	} else {
 		/* Queue to software queue */
@@ -2467,6 +2479,22 @@ ath_tx_tid_unsched(struct ath_softc *sc,
 }
 
 /*
+ * Update the CLRDMASK bit in the ath_buf if it needs to be set.
+ */
+static void
+ath_tx_update_clrdmask(struct ath_softc *sc, struct ath_tid *tid,
+    struct ath_buf *bf)
+{
+
+	ATH_TID_LOCK_ASSERT(sc, tid);
+
+	if (tid->clrdmask == 1) {
+		bf->bf_state.bfs_txflags |= HAL_TXDESC_CLRDMASK;
+		tid->clrdmask = 0;
+	}
+}
+
+/*
  * Assign a sequence number manually to the given frame.
  *
  * This should only be called for A-MPDU TX frames.
@@ -2582,6 +2610,9 @@ ath_tx_xmit_aggr(struct ath_softc *sc, s
 		bf->bf_state.bfs_nframes = 1;
 	}
 
+	/* Update CLRDMASK just before this frame is queued */
+	ath_tx_update_clrdmask(sc, tid, bf);
+
 	/* Direct dispatch to hardware */
 	ath_tx_do_ratelookup(sc, bf);
 	ath_tx_calc_duration(sc, bf);
@@ -2701,6 +2732,7 @@ ath_tx_swq(struct ath_softc *sc, struct 
 	} else if (txq->axq_depth < sc->sc_hwq_limit) {
 		/* AMPDU not running, attempt direct dispatch */
 		DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: xmit_normal\n", __func__);
+		ath_tx_update_clrdmask(sc, atid, bf);
 		ath_tx_xmit_normal(sc, txq, bf);
 	} else {
 		/* Busy; queue */
@@ -2789,6 +2821,12 @@ ath_tx_tid_resume(struct ath_softc *sc, 
 		return;
 	}
 
+	/*
+	 * Override the clrdmask configuration for the next frame,
+	 * just to get the ball rolling.
+	 */
+	tid->clrdmask = 1;
+
 	ath_tx_tid_sched(sc, tid);
 	/* Punt some frames to the hardware if needed */
 	//ath_txq_sched(sc, sc->sc_ac2q[tid->ac]);
@@ -3109,6 +3147,12 @@ ath_tx_tid_bar_tx(struct ath_softc *sc, 
 	tid->bar_tx = 1;
 
 	/*
+	 * Override the clrdmask configuration for the next frame,
+	 * just to get the ball rolling.
+	 */
+	tid->clrdmask = 1;
+
+	/*
 	 * Calculate new BAW left edge, now that all frames have either
 	 * succeeded or failed.
 	 *
@@ -3189,6 +3233,12 @@ ath_tx_tid_drain_print(struct ath_softc 
 	    SEQNO(bf->bf_state.bfs_seqno),
 	    bf->bf_state.bfs_retries);
 	device_printf(sc->sc_dev,
+	    "%s: node %p: bf=%p: txq axq_depth=%d, axq_aggr_depth=%d\n",
+	        __func__, ni, bf,
+		txq->axq_depth,
+		txq->axq_aggr_depth);
+
+	device_printf(sc->sc_dev,
 	    "%s: node %p: bf=%p: tid txq_depth=%d hwq_depth=%d, bar_wait=%d, isfiltered=%d\n",
 	    __func__, ni, bf,
 	    tid->axq_depth,
@@ -3196,13 +3246,13 @@ ath_tx_tid_drain_print(struct ath_softc 
 	    tid->bar_wait,
 	    tid->isfiltered);
 	device_printf(sc->sc_dev,
-	    "%s: node %p: tid %d: txq_depth=%d, "
-	    "txq_aggr_depth=%d, sched=%d, paused=%d, "
-	    "hwq_depth=%d, incomp=%d, baw_head=%d, "
+	    "%s: node %p: tid %d: "
+	    "sched=%d, paused=%d, "
+	    "incomp=%d, baw_head=%d, "
 	    "baw_tail=%d txa_start=%d, ni_txseqs=%d\n",
-	     __func__, ni, tid->tid, txq->axq_depth,
-	     txq->axq_aggr_depth, tid->sched, tid->paused,
-	     tid->hwq_depth, tid->incomp, tid->baw_head,
+	     __func__, ni, tid->tid,
+	     tid->sched, tid->paused,
+	     tid->incomp, tid->baw_head,
 	     tid->baw_tail, tap == NULL ? -1 : tap->txa_start,
 	     ni->ni_txseqs[tid->tid]);
 
@@ -3274,6 +3324,15 @@ ath_tx_tid_drain(struct ath_softc *sc, s
 	}
 
 	/*
+	 * Override the clrdmask configuration for the next frame
+	 * in case there is some future transmission, just to get
+	 * the ball rolling.
+	 *
+	 * This won't hurt things if the TID is about to be freed.
+	 */
+	tid->clrdmask = 1;
+
+	/*
 	 * Now that it's completed, grab the TID lock and update
 	 * the sequence number and BAW window.
 	 * Because sequence numbers have been assigned to frames
@@ -4511,6 +4570,9 @@ ath_tx_tid_hw_queue_aggr(struct ath_soft
 			bf->bf_state.bfs_aggr = 0;
 			bf->bf_state.bfs_nframes = 1;
 
+			/* Update CLRDMASK just before this frame is queued */
+			ath_tx_update_clrdmask(sc, tid, bf);
+
 			ath_tx_do_ratelookup(sc, bf);
 			ath_tx_calc_duration(sc, bf);
 			ath_tx_calc_protection(sc, bf);
@@ -4573,6 +4635,10 @@ ath_tx_tid_hw_queue_aggr(struct ath_soft
 		if (bf->bf_state.bfs_nframes == 1) {
 			DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
 			    "%s: single-frame aggregate\n", __func__);
+
+			/* Update CLRDMASK just before this frame is queued */
+			ath_tx_update_clrdmask(sc, tid, bf);
+
 			bf->bf_state.bfs_aggr = 0;
 			bf->bf_state.bfs_ndelim = 0;
 			ath_tx_setds(sc, bf);
@@ -4591,6 +4657,9 @@ ath_tx_tid_hw_queue_aggr(struct ath_soft
 			sc->sc_aggr_stats.aggr_pkts[bf->bf_state.bfs_nframes]++;
 			sc->sc_aggr_stats.aggr_aggr_pkt++;
 
+			/* Update CLRDMASK just before this frame is queued */
+			ath_tx_update_clrdmask(sc, tid, bf);
+
 			/*
 			 * Calculate the duration/protection as required.
 			 */
@@ -4654,7 +4723,7 @@ ath_tx_tid_hw_queue_norm(struct ath_soft
 	DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: node %p: TID %d: called\n",
 	    __func__, an, tid->tid);
 
-	ATH_TXQ_LOCK_ASSERT(txq);
+	ATH_TID_LOCK_ASSERT(sc, tid);
 
 	/* Check - is AMPDU pending or running? then print out something */
 	if (ath_tx_ampdu_pending(sc, an, tid->tid))
@@ -4691,6 +4760,9 @@ ath_tx_tid_hw_queue_norm(struct ath_soft
 		/* Normal completion handler */
 		bf->bf_comp = ath_tx_normal_comp;
 
+		/* Update CLRDMASK just before this frame is queued */
+		ath_tx_update_clrdmask(sc, tid, bf);
+
 		/* Program descriptors + rate control */
 		ath_tx_do_ratelookup(sc, bf);
 		ath_tx_calc_duration(sc, bf);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201209200313.q8K3DKlO028959>