svn commit: r225072 - in user/adrian/if_ath_tx/sys/dev/ath: . ath_rate/sample

Adrian Chadd adrian at FreeBSD.org
Mon Aug 22 06:25:10 UTC 2011


Author: adrian
Date: Mon Aug 22 06:25:01 2011
New Revision: 225072
URL: http://svn.freebsd.org/changeset/base/225072

Log:
  Do some reasonably major surgery to the way TX rates are calculated
  and completed, as part of providing the rate control code with accurate
  information about aggregate packet completions.
  
  Since the aggregate completion function has no idea how many frames
  have succeeded or failed until -after- the ath_buf list has been walked,
  compared against the Blockack bitmap (and buffers have been completed),
  we need to keep a variety of the state somewhere.
  
  So we can't just pass in an ath_buf into the completion code - it has
  likely already been freed before the rate update call is made.
  
  Also, the framelength for an aggregate is the aggregate itself, not the
  length of the first frame.
  
  The specifics:
  
  * add a 'ratecode' field to ath_rc_series, storing the ratecode decision;
  * update ratecode in ath_tx_rate_fill_rcflags(), also taking into account
    whether the ath_buf has the short preamble bit set;
  * modify the sample ath_tx_rate_complete() function to take a copy of the
    ath_rc_series, along with a framelength
  * if a buffer doesn't have a completion handler, manually call the rate
    control code
  * if a buffer -does- have a completion handler, leave calling the rate
    control code up to that.
  
  The things to do:
  
  * Actually teach ath_rate_sample about the packet error rate when TX'ing
    aggregates. That's next.
  
  * Becuase the rate lookup is done before the aggregate is formed, we can't
    query the rate control code with the length of the aggregate. It's a chicken
    and egg problem - we can't form aggregates until we know what the rate
    selection is (as that's used to enforce the 4ms frame max duration) and
    delimiter density. So for now, it'll just use the size of the first frame
    in the list when making a rate decision, and I'll worry about delaying
    the rate control lookup later.

Modified:
  user/adrian/if_ath_tx/sys/dev/ath/ath_rate/sample/sample.c
  user/adrian/if_ath_tx/sys/dev/ath/if_ath.c
  user/adrian/if_ath_tx/sys/dev/ath/if_ath_misc.h
  user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.c
  user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx_ht.c
  user/adrian/if_ath_tx/sys/dev/ath/if_athrate.h

Modified: user/adrian/if_ath_tx/sys/dev/ath/ath_rate/sample/sample.c
==============================================================================
--- user/adrian/if_ath_tx/sys/dev/ath/ath_rate/sample/sample.c	Mon Aug 22 05:03:43 2011	(r225071)
+++ user/adrian/if_ath_tx/sys/dev/ath/ath_rate/sample/sample.c	Mon Aug 22 06:25:01 2011	(r225072)
@@ -594,21 +594,20 @@ badrate(struct ifnet *ifp, int series, i
 
 void
 ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
-	const struct ath_buf *bf)
+	const struct ath_rc_series *rc, const struct ath_tx_status *ts,
+	int frame_size, int nframes, int nbad)
 {
 	struct ifnet *ifp = sc->sc_ifp;
 	struct ieee80211com *ic = ifp->if_l2com;
 	struct sample_node *sn = ATH_NODE_SAMPLE(an);
-	const struct ath_tx_status *ts = &bf->bf_status.ds_txstat;
-	const struct ath_desc *ds0 = &bf->bf_desc[0];
-	int final_rix, short_tries, long_tries, frame_size;
+	int final_rix, short_tries, long_tries;
 	const HAL_RATE_TABLE *rt = sc->sc_currates;
 	int mrr;
 
 	final_rix = rt->rateCodeToIndex[ts->ts_rate];
 	short_tries = ts->ts_shortretry;
 	long_tries = ts->ts_longretry + 1;
-	frame_size = ds0->ds_ctl0 & 0x0fff; /* low-order 12 bits of ds_ctl0 */
+
 	if (frame_size == 0)		    /* NB: should not happen */
 		frame_size = 1500;
 
@@ -645,18 +644,12 @@ ath_rate_tx_complete(struct ath_softc *s
 			     0, 0,
 			     short_tries, long_tries, ts->ts_status);
 	} else {
-		int hwrates[4], tries[4], rix[4];
 		int finalTSIdx = ts->ts_finaltsi;
 		int i;
 
 		/*
 		 * Process intermediate rates that failed.
 		 */
-		ath_hal_gettxcompletionrates(sc->sc_ah, ds0, hwrates, tries);
-
-		for (i = 0; i < 4; i++) {
-			rix[i] = rt->rateCodeToIndex[hwrates[i]];
-		}
 
 		IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL,
 		    &an->an_node,
@@ -665,16 +658,21 @@ ath_rate_tx_complete(struct ath_softc *s
 		     bin_to_size(size_to_bin(frame_size)),
 		     frame_size,
 		     finalTSIdx,
-		     long_tries, 
+		     long_tries,
 		     ts->ts_status ? "FAIL" : "OK",
-		     dot11rate(rt, rix[0]), dot11rate_label(rt, rix[0]), tries[0],
-		     dot11rate(rt, rix[1]), dot11rate_label(rt, rix[1]), tries[1],
-		     dot11rate(rt, rix[2]), dot11rate_label(rt, rix[2]), tries[2],
-		     dot11rate(rt, rix[3]), dot11rate_label(rt, rix[3]), tries[3]);
+		     dot11rate(rt, rc[0].rix),
+		      dot11rate_label(rt, rc[0].rix), rc[0].tries,
+		     dot11rate(rt, rc[1].rix),
+		      dot11rate_label(rt, rc[1].rix), rc[1].tries,
+		     dot11rate(rt, rc[2].rix),
+		      dot11rate_label(rt, rc[2].rix), rc[2].tries,
+		     dot11rate(rt, rc[3].rix),
+		      dot11rate_label(rt, rc[3].rix), rc[3].tries);
 
 		for (i = 0; i < 4; i++) {
-			if (tries[i] && !IS_RATE_DEFINED(sn, rix[i]))
-				badrate(ifp, 0, hwrates[i], tries[i], ts->ts_status);
+			if (rc[i].tries && !IS_RATE_DEFINED(sn, rc[i].rix))
+				badrate(ifp, 0, rc[i].ratecode, rc[i].tries,
+				    ts->ts_status);
 		}
 
 		/*
@@ -684,46 +682,46 @@ ath_rate_tx_complete(struct ath_softc *s
 		 * sample higher rates 1 try at a time doing so
 		 * may unfairly penalize them.
 		 */
-		if (tries[0]) {
-			update_stats(sc, an, frame_size, 
-				     rix[0], tries[0], 
-				     rix[1], tries[1], 
-				     rix[2], tries[2], 
-				     rix[3], tries[3], 
-				     short_tries, long_tries, 
-				     long_tries > tries[0]);
-			long_tries -= tries[0];
+		if (rc[0].tries) {
+			update_stats(sc, an, frame_size,
+				     rc[0].rix, rc[0].tries,
+				     rc[1].rix, rc[1].tries,
+				     rc[2].rix, rc[2].tries,
+				     rc[3].rix, rc[3].tries,
+				     short_tries, long_tries,
+				     long_tries > rc[0].tries);
+			long_tries -= rc[0].tries;
 		}
 		
-		if (tries[1] && finalTSIdx > 0) {
-			update_stats(sc, an, frame_size, 
-				     rix[1], tries[1], 
-				     rix[2], tries[2], 
-				     rix[3], tries[3], 
-				     0, 0, 
-				     short_tries, long_tries, 
+		if (rc[1].tries && finalTSIdx > 0) {
+			update_stats(sc, an, frame_size,
+				     rc[1].rix, rc[1].tries,
+				     rc[2].rix, rc[2].tries,
+				     rc[3].rix, rc[3].tries,
+				     0, 0,
+				     short_tries, long_tries,
 				     ts->ts_status);
-			long_tries -= tries[1];
+			long_tries -= rc[1].tries;
 		}
 
-		if (tries[2] && finalTSIdx > 1) {
-			update_stats(sc, an, frame_size, 
-				     rix[2], tries[2], 
-				     rix[3], tries[3], 
+		if (rc[2].tries && finalTSIdx > 1) {
+			update_stats(sc, an, frame_size,
+				     rc[2].rix, rc[2].tries,
+				     rc[3].rix, rc[3].tries,
 				     0, 0,
 				     0, 0,
-				     short_tries, long_tries, 
+				     short_tries, long_tries,
 				     ts->ts_status);
-			long_tries -= tries[2];
+			long_tries -= rc[2].tries;
 		}
 
-		if (tries[3] && finalTSIdx > 2) {
-			update_stats(sc, an, frame_size, 
-				     rix[3], tries[3],
+		if (rc[3].tries && finalTSIdx > 2) {
+			update_stats(sc, an, frame_size,
+				     rc[3].rix, rc[3].tries,
 				     0, 0,
 				     0, 0,
 				     0, 0,
-				     short_tries, long_tries, 
+				     short_tries, long_tries,
 				     ts->ts_status);
 		}
 	}

Modified: user/adrian/if_ath_tx/sys/dev/ath/if_ath.c
==============================================================================
--- user/adrian/if_ath_tx/sys/dev/ath/if_ath.c	Mon Aug 22 05:03:43 2011	(r225071)
+++ user/adrian/if_ath_tx/sys/dev/ath/if_ath.c	Mon Aug 22 06:25:01 2011	(r225072)
@@ -4206,6 +4206,29 @@ ath_tx_default_comp(struct ath_softc *sc
 }
 
 /*
+ * Update rate control with the given completion status.
+ */
+void
+ath_tx_update_ratectrl(struct ath_softc *sc, struct ieee80211_node *ni,
+    struct ath_rc_series *rc, struct ath_tx_status *ts, int frmlen,
+    int nframes, int nbad)
+{
+	struct ath_node *an;
+
+	/* Only for unicast frames */
+	if (ni == NULL)
+		return;
+
+	an = ATH_NODE(ni);
+
+	if ((ts->ts_status & HAL_TXERR_FILT) == 0) {
+		ATH_NODE_LOCK(an);
+		ath_rate_tx_complete(sc, an, rc, ts, frmlen, nframes, nbad);
+		ATH_NODE_UNLOCK(an);
+	}
+}
+
+/*
  * Process completed xmit descriptors from the specified queue.
  * Kick the packet scheduler if needed. This can occur from this
  * particular task.
@@ -4283,21 +4306,31 @@ ath_tx_processq(struct ath_softc *sc, st
 			an = ATH_NODE(ni);
 			/* update statistics */
 			ath_tx_update_stats(sc, ts, bf);
+		}
 
-			/*
-			 * Hand the descriptor to the rate control algorithm.
-			 */
+
+		/*
+		 * Call the completion handler.
+		 * The completion handler is responsible for
+		 * calling the rate control code.
+		 *
+		 * Frames with no completion handler get the
+		 * rate control code called here.
+		 */
+		if (bf->bf_comp == NULL) {
 			if ((ts->ts_status & HAL_TXERR_FILT) == 0 &&
 			    (bf->bf_txflags & HAL_TXDESC_NOACK) == 0) {
-				ATH_NODE_LOCK(an);
-				ath_rate_tx_complete(sc, an, bf);
-				ATH_NODE_UNLOCK(an);
-			}
-		}
-
-		if (bf->bf_comp == NULL)
+				/*
+				 * XXX assume this isn't an aggregate
+				 * frame.
+				 */
+				ath_tx_update_ratectrl(sc, ni,
+				     bf->bf_state.bfs_rc, ts,
+				    bf->bf_state.bfs_pktlen, 1,
+				    (ts->ts_status == 0 ? 0 : 1));
 			ath_tx_default_comp(sc, bf, 0);
-		else
+			}
+		} else
 			bf->bf_comp(sc, bf, 0);
 	}
 #ifdef IEEE80211_SUPPORT_SUPERG

Modified: user/adrian/if_ath_tx/sys/dev/ath/if_ath_misc.h
==============================================================================
--- user/adrian/if_ath_tx/sys/dev/ath/if_ath_misc.h	Mon Aug 22 05:03:43 2011	(r225071)
+++ user/adrian/if_ath_tx/sys/dev/ath/if_ath_misc.h	Mon Aug 22 06:25:01 2011	(r225072)
@@ -57,6 +57,10 @@ extern int ath_reset(struct ifnet *);
 extern void ath_tx_draintxq(struct ath_softc *sc, struct ath_txq *txq);
 extern void ath_tx_default_comp(struct ath_softc *sc, struct ath_buf *bf,
 	    int fail);
+extern void ath_tx_update_ratectrl(struct ath_softc *sc,
+	    struct ieee80211_node *ni, struct ath_rc_series *rc,
+	    struct ath_tx_status *ts, int frmlen, int nframes, int nbad);
+
 extern void ath_tx_freebuf(struct ath_softc *sc, struct ath_buf *bf,
     int status);
 extern void ath_tx_sched_proc_sched(struct ath_softc *sc, struct ath_txq *txq);

Modified: user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.c
==============================================================================
--- user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.c	Mon Aug 22 05:03:43 2011	(r225071)
+++ user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.c	Mon Aug 22 06:25:01 2011	(r225072)
@@ -760,26 +760,17 @@ static void
 ath_tx_set_ratectrl(struct ath_softc *sc, struct ieee80211_node *ni,
     struct ath_buf *bf)
 {
-	const HAL_RATE_TABLE *rt = sc->sc_currates;
 	struct ath_rc_series *rc = bf->bf_state.bfs_rc;
-	uint8_t rate[4];
-	int i;
 
 	if (ath_tx_is_11n(sc)) {
 		/* Always setup rate series */
 		ath_buf_set_rate(sc, ni, bf);
 	} else if (bf->bf_state.bfs_ismrr) {
 		/* Only call for legacy NICs if MRR */
-		for (i = 0; i < 4; i++) {
-			rate[i] = rt->info[rc[i].rix].rateCode;
-			if (bf->bf_state.bfs_shpream) {
-				rate[i] |= rt->info[rc[i].rix].shortPreamble;
-			}
-		}
 		ath_hal_setupxtxdesc(sc->sc_ah, bf->bf_desc
-			, rate[1], rc[1].tries
-			, rate[2], rc[2].tries
-			, rate[3], rc[3].tries
+			, rc[1].ratecode, rc[1].tries
+			, rc[2].ratecode, rc[2].tries
+			, rc[3].ratecode, rc[3].tries
 		);
 	}
 }
@@ -1129,6 +1120,7 @@ ath_tx_normal_setup(struct ath_softc *sc
 	 */
 	bf->bf_state.bfs_rc[0].rix = rix;
 	bf->bf_state.bfs_rc[0].tries = try0;
+	bf->bf_state.bfs_rc[0].ratecode = txrate;
 
 	/* Store the decided rate index values away */
 	bf->bf_state.bfs_pktlen = pktlen;
@@ -1498,17 +1490,21 @@ ath_tx_raw_start(struct ath_softc *sc, s
 	bf->bf_state.bfs_rc[0].rix =
 	    ath_tx_findrix(sc, params->ibp_rate0);
 	bf->bf_state.bfs_rc[0].tries = try0;
+	bf->bf_state.bfs_rc[0].ratecode = txrate;
 
 	if (ismrr) {
-		bf->bf_state.bfs_rc[1].rix =
-		    ath_tx_findrix(sc, params->ibp_rate1);
-		bf->bf_state.bfs_rc[2].rix =
-		    ath_tx_findrix(sc, params->ibp_rate2);
-		bf->bf_state.bfs_rc[3].rix =
-		    ath_tx_findrix(sc, params->ibp_rate3);
+		int rix;
 
+		rix = ath_tx_findrix(sc, params->ibp_rate1);
+		bf->bf_state.bfs_rc[1].rix = rix;
 		bf->bf_state.bfs_rc[1].tries = params->ibp_try1;
+
+		rix = ath_tx_findrix(sc, params->ibp_rate2);
+		bf->bf_state.bfs_rc[2].rix = rix;
 		bf->bf_state.bfs_rc[2].tries = params->ibp_try2;
+
+		rix = ath_tx_findrix(sc, params->ibp_rate3);
+		bf->bf_state.bfs_rc[3].rix = rix;
 		bf->bf_state.bfs_rc[3].tries = params->ibp_try3;
 	}
 	/*
@@ -2179,6 +2175,7 @@ ath_tx_normal_comp(struct ath_softc *sc,
 	struct ath_node *an = ATH_NODE(ni);
 	int tid = bf->bf_state.bfs_tid;
 	struct ath_tid *atid = &an->an_tid[tid];
+	struct ath_tx_status *ts = &bf->bf_status.ds_txstat;
 
 	DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: bf=%p: fail=%d, hwq_depth now %d\n",
 	    __func__, bf, fail, atid->hwq_depth - 1);
@@ -2190,6 +2187,15 @@ ath_tx_normal_comp(struct ath_softc *sc,
 		    __func__, atid->hwq_depth);
 	ATH_TXQ_UNLOCK(atid);
 
+	/*
+	 * punt to rate control if we're not being cleaned up
+	 * during a hw queue drain.
+	 */
+	if (fail == 0)
+		ath_tx_update_ratectrl(sc, ni, bf->bf_state.bfs_rc,
+		    ts, bf->bf_state.bfs_pktlen,
+		    1, (ts->ts_status == 0) ? 0 : 1);
+
 	ath_tx_default_comp(sc, bf, fail);
 }
 
@@ -2514,6 +2520,14 @@ ath_tx_comp_aggr_error(struct ath_softc 
 
 	TAILQ_INIT(&bf_q);
 
+	/*
+	 * Update rate control - all frames have failed.
+	 */
+	ath_tx_update_ratectrl(sc, ni, bf_first->bf_state.bfs_rc,
+	    &bf_first->bf_status.ds_txstat,
+	    bf_first->bf_state.bfs_al,
+	    bf_first->bf_state.bfs_nframes, bf_first->bf_state.bfs_nframes);
+
 	/* Retry all subframes */
 	bf = bf_first;
 	while (bf) {
@@ -2523,9 +2537,6 @@ ath_tx_comp_aggr_error(struct ath_softc 
 		bf = bf_next;
 	}
 
-	/* Update rate control module about aggregation */
-	/* XXX todo */
-
 #if 0
 	/*
 	 * send bar if we dropped any frames
@@ -2579,7 +2590,7 @@ ath_tx_comp_cleanup_aggr(struct ath_soft
 		atid->incomp--;
 		bf_next = bf->bf_next;
 		bf->bf_next = NULL;	/* Remove it from the aggr list */
-		ath_tx_default_comp(sc, bf, -1);
+		ath_tx_default_comp(sc, bf, 1);
 		bf = bf_next;
 	}
 
@@ -2609,7 +2620,7 @@ ath_tx_aggr_comp_aggr(struct ath_softc *
 	struct ath_node *an = ATH_NODE(ni);
 	int tid = bf_first->bf_state.bfs_tid;
 	struct ath_tid *atid = &an->an_tid[tid];
-	struct ath_tx_status *ts = &bf_first->bf_status.ds_txstat;
+	struct ath_tx_status ts;
 	struct ieee80211_tx_ampdu *tap;
 	ath_bufhead bf_q;
 	int seq_st, tx_ok;
@@ -2619,7 +2630,10 @@ ath_tx_aggr_comp_aggr(struct ath_softc *
 	int ba_index;
 	int drops = 0;
 	struct ath_txq *txq = sc->sc_ac2q[atid->ac];
-	int np = 0;
+	int nframes = 0, nbad = 0;
+	int pktlen;
+	/* XXX there's too much on the stack? */
+	struct ath_rc_series rc[4];
 
 	DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR, "%s: called; hwq_depth=%d\n",
 	    __func__, atid->hwq_depth);
@@ -2640,9 +2654,16 @@ ath_tx_aggr_comp_aggr(struct ath_softc *
 	}
 
 	/*
+	 * Take a copy; this may be needed -after- bf_first
+	 * has been completed and freed.
+	 */
+	ts = bf_first->bf_status.ds_txstat;
+	pktlen = bf_first->bf_state.bfs_al;
+
+	/*
 	 * handle errors first
 	 */
-	if (ts->ts_status & HAL_TXERR_XRETRY) {
+	if (ts.ts_status & HAL_TXERR_XRETRY) {
 		ath_tx_comp_aggr_error(sc, bf_first, atid);
 		return;
 	}
@@ -2654,22 +2675,30 @@ ath_tx_aggr_comp_aggr(struct ath_softc *
 	 * extract starting sequence and block-ack bitmap
 	 */
 	/* XXX endian-ness of seq_st, ba? */
-	seq_st = ts->ts_seqnum;
-	hasba = !! (ts->ts_flags & HAL_TX_BA);
-	tx_ok = (ts->ts_status == 0);
+	seq_st = ts.ts_seqnum;
+	hasba = !! (ts.ts_flags & HAL_TX_BA);
+	tx_ok = (ts.ts_status == 0);
 	isaggr = bf_first->bf_state.bfs_aggr;
-	ba[0] = ts->ts_ba_low;
-	ba[1] = ts->ts_ba_high;
+	ba[0] = ts.ts_ba_low;
+	ba[1] = ts.ts_ba_high;
+
+	/*
+	 * Copy the TX completion status and the rate control
+	 * series from the first descriptor, as it may be freed
+	 * before the rate control code can get its grubby fingers
+	 * into things.
+	 */
+	memcpy(rc, bf_first->bf_state.bfs_rc, sizeof(rc));
 
 	DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
 	    "%s: txa_start=%d, tx_ok=%d, status=%.8x, flags=%.8x, isaggr=%d, seq_st=%d, hasba=%d, ba=%.8x, %.8x\n",
-	    __func__, tap->txa_start, tx_ok, ts->ts_status, ts->ts_flags,
+	    __func__, tap->txa_start, tx_ok, ts.ts_status, ts.ts_flags,
 	    isaggr, seq_st, hasba, ba[0], ba[1]);
 
 	/* Occasionally, the MAC sends a tx status for the wrong TID. */
-	if (tid != ts->ts_tid) {
+	if (tid != ts.ts_tid) {
 		device_printf(sc->sc_dev, "%s: tid %d != hw tid %d\n",
-		    __func__, tid, ts->ts_tid);
+		    __func__, tid, ts.ts_tid);
 		tx_ok = 0;
 	}
 
@@ -2683,7 +2712,7 @@ ath_tx_aggr_comp_aggr(struct ath_softc *
 	bf = bf_first;
 
 	while (bf) {
-		np++;
+		nframes++;
 		ba_index = ATH_BA_INDEX(seq_st, SEQNO(bf->bf_state.bfs_seqno));
 		bf_next = bf->bf_next;
 		bf->bf_next = NULL;	/* Remove it from the aggr list */
@@ -2706,16 +2735,21 @@ ath_tx_aggr_comp_aggr(struct ath_softc *
 			ath_tx_default_comp(sc, bf, 0);
 		} else {
 			drops += ath_tx_retry_subframe(sc, bf, &bf_q);
+			nbad++;
 		}
 		bf = bf_next;
 	}
 
-	if (np != bf_first->bf_state.bfs_nframes)
+	if (nframes != bf_first->bf_state.bfs_nframes)
 		device_printf(sc->sc_dev, "%s: np=%d; nframes=%d\n",
-		    __func__, np, bf_first->bf_state.bfs_nframes);
+		    __func__, nframes, bf_first->bf_state.bfs_nframes);
 
-	/* update rate control module about aggregate status */
-	/* XXX TODO */
+	/*
+	 * Now we know how many frames were bad, call the rate
+	 * control code.
+	 */
+	if (fail == 0)
+		ath_tx_update_ratectrl(sc, ni, rc, &ts, pktlen, nframes, nbad);
 
 #if 0
 	/*
@@ -2783,6 +2817,16 @@ ath_tx_aggr_comp_unaggr(struct ath_softc
 		    __func__, atid->hwq_depth);
 	ATH_TXQ_UNLOCK(atid);
 
+	/*
+	 * Update rate control status here, before we possibly
+	 * punt to retry or cleanup.
+	 */
+	if (fail == 0)
+		ath_tx_update_ratectrl(sc, ni, bf->bf_state.bfs_rc,
+		    &bf->bf_status.ds_txstat,
+		    bf->bf_state.bfs_pktlen,
+		    1, (ts->ts_status == 0) ? 0 : 1);
+
 	ATH_TXQ_LOCK(sc->sc_ac2q[atid->ac]);
 	ath_tx_tid_sched(sc, an, atid->tid);
 	ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->ac]);
@@ -2791,7 +2835,7 @@ ath_tx_aggr_comp_unaggr(struct ath_softc
 	 * If a cleanup is in progress, punt to comp_cleanup;
 	 * rather than handling it here. It's thus their
 	 * responsibility to clean up, call the completion
-	 * function in net80211, update rate control, etc.
+	 * function in net80211, etc.
 	 */
 	if (atid->cleanup_inprogress) {
 		ath_tx_comp_cleanup_unaggr(sc, bf);
@@ -2955,6 +2999,11 @@ ath_tx_tid_hw_queue_aggr(struct ath_soft
 			bf->bf_state.bfs_rc[1].rix =
 			bf->bf_state.bfs_rc[2].rix =
 			bf->bf_state.bfs_rc[3].rix = 0;
+
+			bf->bf_state.bfs_rc[1].ratecode =
+			bf->bf_state.bfs_rc[2].ratecode =
+			bf->bf_state.bfs_rc[3].ratecode = 0;
+
 			bf->bf_state.bfs_rc[1].tries =
 			bf->bf_state.bfs_rc[2].tries =
 			bf->bf_state.bfs_rc[3].tries = 0;

Modified: user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx_ht.c
==============================================================================
--- user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx_ht.c	Mon Aug 22 05:03:43 2011	(r225071)
+++ user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx_ht.c	Mon Aug 22 06:25:01 2011	(r225072)
@@ -234,6 +234,17 @@ ath_tx_rate_fill_rcflags(struct ath_soft
 
 		rate = rt->info[rc[i].rix].rateCode;
 
+		/*
+		 * XXX only do this for legacy rates?
+		 */
+		if (bf->bf_state.bfs_shpream)
+			rate |= rt->info[rc[i].rix].shortPreamble;
+
+		/*
+		 * Save this, used by the TX and completion code
+		 */
+		rc[i].ratecode = rate;
+
 		if (bf->bf_state.bfs_flags &
 		    (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA))
 			rc[i].flags |= ATH_RC_RTSCTS_FLAG;

Modified: user/adrian/if_ath_tx/sys/dev/ath/if_athrate.h
==============================================================================
--- user/adrian/if_ath_tx/sys/dev/ath/if_athrate.h	Mon Aug 22 05:03:43 2011	(r225071)
+++ user/adrian/if_ath_tx/sys/dev/ath/if_athrate.h	Mon Aug 22 06:25:01 2011	(r225072)
@@ -87,6 +87,7 @@ void	ath_rate_detach(struct ath_ratectrl
 
 struct ath_rc_series {
 	uint8_t rix;		/* ratetable index, not rate code */
+	uint8_t ratecode;	/* hardware rate code */
 	uint8_t tries;
 	uint8_t flags;
 	uint32_t max4msframelen;
@@ -141,8 +142,12 @@ void	ath_rate_setupxtxdesc(struct ath_so
  * supplied transmit descriptor.  The routine is invoked both
  * for packets that were successfully sent and for those that
  * failed (consult the descriptor for details).
+ *
+ * For A-MPDU frames, nframes and nbad indicate how many frames
+ * were in the aggregate, and how many failed.
  */
 struct ath_buf;
 void	ath_rate_tx_complete(struct ath_softc *, struct ath_node *,
-		const struct ath_buf *);
+		const struct ath_rc_series *, const struct ath_tx_status *,
+		int pktlen, int nframes, int nbad);
 #endif /* _ATH_RATECTRL_H_ */


More information about the svn-src-user mailing list