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

Adrian Chadd adrian at FreeBSD.org
Tue Nov 8 21:25:36 UTC 2011


Author: adrian
Date: Tue Nov  8 21:25:36 2011
New Revision: 227360
URL: http://svn.freebsd.org/changeset/base/227360

Log:
  Change the descriptor logic to use bf_lastds to point to the last
  descriptor, rather than using the maths involving bf_desc[bf_nseg - 1].
  
  When doing TX aggregation, the status will be updated in the -final-
  descriptor of the -final- subframe in an aggregate. Thus bf_lastds
  may point to the last descriptor in a completely different ath_buf.
  
  Sponsored by:	Hobnob, Inc.

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

Modified: head/sys/dev/ath/if_ath.c
==============================================================================
--- head/sys/dev/ath/if_ath.c	Tue Nov  8 21:13:05 2011	(r227359)
+++ head/sys/dev/ath/if_ath.c	Tue Nov  8 21:25:36 2011	(r227360)
@@ -2503,6 +2503,8 @@ ath_beacon_setup(struct ath_softc *sc, s
 
 	/* setup descriptors */
 	ds = bf->bf_desc;
+	bf->bf_last = bf;
+	bf->bf_lastds = ds;
 
 	flags = HAL_TXDESC_NOACK;
 	if (ic->ic_opmode == IEEE80211_M_IBSS && sc->sc_hasveol) {
@@ -2582,7 +2584,9 @@ ath_txqmove(struct ath_txq *dst, struct 
 	dst->axq_link = src->axq_link;
 	src->axq_link = NULL;
 	dst->axq_depth += src->axq_depth;
+	dst->axq_aggr_depth += src->axq_aggr_depth;
 	src->axq_depth = 0;
+	src->axq_aggr_depth = 0;
 }
 
 /*
@@ -3227,6 +3231,7 @@ ath_descdma_setup(struct ath_softc *sc,
 			ath_descdma_cleanup(sc, dd, head);
 			return error;
 		}
+		bf->bf_lastds = bf->bf_desc;	/* Just an initial value */
 		TAILQ_INSERT_TAIL(head, bf, bf_list);
 	}
 	return 0;
@@ -4284,7 +4289,7 @@ ath_tx_processq(struct ath_softc *sc, st
 	struct ifnet *ifp = sc->sc_ifp;
 	struct ieee80211com *ic = ifp->if_l2com;
 	struct ath_buf *bf, *last;
-	struct ath_desc *ds, *ds0;
+	struct ath_desc *ds;
 	struct ath_tx_status *ts;
 	struct ieee80211_node *ni;
 	struct ath_node *an;
@@ -4304,8 +4309,7 @@ ath_tx_processq(struct ath_softc *sc, st
 			ATH_TXQ_UNLOCK(txq);
 			break;
 		}
-		ds0 = &bf->bf_desc[0];
-		ds = &bf->bf_desc[bf->bf_nseg - 1];
+		ds = bf->bf_lastds;	/* XXX must be setup correctly! */
 		ts = &bf->bf_status.ds_txstat;
 		status = ath_hal_txprocdesc(ah, ds, ts);
 #ifdef ATH_DEBUG
@@ -4324,13 +4328,19 @@ ath_tx_processq(struct ath_softc *sc, st
 			 * More frames follow.  Mark the buffer busy
 			 * so it's not re-used while the hardware may
 			 * still re-read the link field in the descriptor.
+			 *
+			 * Use the last buffer in an aggregate as that
+			 * is where the hardware may be - intermediate
+			 * descriptors won't be "busy".
 			 */
-			bf->bf_flags |= ATH_BUF_BUSY;
+			bf->bf_last->bf_flags |= ATH_BUF_BUSY;
 		} else
 #else
 		if (txq->axq_depth == 0)
 #endif
 			txq->axq_link = NULL;
+		if (bf->bf_state.bfs_aggr)
+			txq->axq_aggr_depth--;
 		ATH_TXQ_UNLOCK(txq);
 
 		ni = bf->bf_node;
@@ -4565,13 +4575,15 @@ ath_tx_draintxq(struct ath_softc *sc, st
 			break;
 		}
 		ATH_TXQ_REMOVE(txq, bf, bf_list);
+		if (bf->bf_state.bfs_aggr)
+			txq->axq_aggr_depth--;
 		ATH_TXQ_UNLOCK(txq);
 #ifdef ATH_DEBUG
 		if (sc->sc_debug & ATH_DEBUG_RESET) {
 			struct ieee80211com *ic = sc->sc_ifp->if_l2com;
 
 			ath_printtxbuf(sc, bf, txq->axq_qnum, ix,
-				ath_hal_txprocdesc(ah, bf->bf_desc,
+				ath_hal_txprocdesc(ah, bf->bf_lastds,
 				    &bf->bf_status.ds_txstat) == HAL_OK);
 			ieee80211_dump_pkt(ic, mtod(bf->bf_m, const uint8_t *),
 			    bf->bf_m->m_len, 0, -1);
@@ -4657,7 +4669,7 @@ ath_draintxq(struct ath_softc *sc, ATH_R
 		struct ath_buf *bf = TAILQ_FIRST(&sc->sc_bbuf);
 		if (bf != NULL && bf->bf_m != NULL) {
 			ath_printtxbuf(sc, bf, sc->sc_bhalq, 0,
-				ath_hal_txprocdesc(ah, bf->bf_desc,
+				ath_hal_txprocdesc(ah, bf->bf_lastds,
 				    &bf->bf_status.ds_txstat) == HAL_OK);
 			ieee80211_dump_pkt(ifp->if_l2com,
 			    mtod(bf->bf_m, const uint8_t *), bf->bf_m->m_len,

Modified: head/sys/dev/ath/if_ath_tx.c
==============================================================================
--- head/sys/dev/ath/if_ath_tx.c	Tue Nov  8 21:13:05 2011	(r227359)
+++ head/sys/dev/ath/if_ath_tx.c	Tue Nov  8 21:25:36 2011	(r227360)
@@ -225,6 +225,9 @@ ath_tx_dmasetup(struct ath_softc *sc, st
 	return 0;
 }
 
+/*
+ * Chain together segments+descriptors for a non-11n frame.
+ */
 static void
 ath_tx_chaindesclist(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf)
 {
@@ -252,8 +255,8 @@ ath_tx_chaindesclist(struct ath_softc *s
 			"%s: %d: %08x %08x %08x %08x %08x %08x\n",
 			__func__, i, ds->ds_link, ds->ds_data,
 			ds->ds_ctl0, ds->ds_ctl1, ds->ds_hw[0], ds->ds_hw[1]);
+		bf->bf_lastds = ds;
 	}
-
 }
 
 static void
@@ -347,7 +350,9 @@ ath_tx_handoff(struct ath_softc *sc, str
 			    (caddr_t)bf->bf_daddr, bf->bf_desc, txq->axq_depth);
 		}
 #endif /* IEEE80211_SUPPORT_TDMA */
-		txq->axq_link = &bf->bf_desc[bf->bf_nseg - 1].ds_link;
+		if (bf->bf_state.bfs_aggr)
+			txq->axq_aggr_depth++;
+		txq->axq_link = &bf->bf_lastds->ds_link;
 		ath_hal_txstart(ah, txq->axq_qnum);
 	} else {
 		if (txq->axq_link != NULL) {


More information about the svn-src-head mailing list