Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 5 Aug 2011 17:15:47 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r224658 - user/adrian/if_ath_tx/sys/dev/ath
Message-ID:  <201108051715.p75HFlpN014470@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: adrian
Date: Fri Aug  5 17:15:46 2011
New Revision: 224658
URL: http://svn.freebsd.org/changeset/base/224658

Log:
  Begin fleshing out BAW tracking.
  
  baw_head/baw_tail implement a sliding window. tx_buf is an array of active
  frames inside the BAW.
  
  Frames that are being TXed are added to the relevant spot in tx_buf, with the
  baw_head/baw_tail sliding window updated.
  
  Frames that have been transmitted (successfully or not) are removed from the
  tx_buf array, and txa_start (the BAW left edge) is then updated.
  
  This is in no way complete and is missing a few things, notably keeping the
  BAW up to date when flushing a TID/node, or when a TID/node aggregation
  session is being torn down. There's no software retransmit, and there's
  currently no support yet for sending a BAR when the TX window has been
  forcibly moved after a TX failure.
  
  There's also a "gap" between the advertised BAW start during ADDBA and the
  first sequence number that is queued as an aggregate frame.
  
  Obtained from:	Atheros

Modified:
  user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.c
  user/adrian/if_ath_tx/sys/dev/ath/if_athvar.h

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	Fri Aug  5 15:07:28 2011	(r224657)
+++ user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.c	Fri Aug  5 17:15:46 2011	(r224658)
@@ -100,6 +100,27 @@ __FBSDID("$FreeBSD$");
 #include <dev/ath/if_ath_tx.h>
 #include <dev/ath/if_ath_tx_ht.h>
 
+/*
+ * some general macros
+ */
+#define	INCR(_l, _sz)		(_l) ++; (_l) &= ((_sz) - 1)
+/*
+ * return block-ack bitmap index given sequence and starting sequence
+ */
+#define	ATH_BA_INDEX(_st, _seq)	(((_seq) - (_st)) & (IEEE80211_SEQ_RANGE - 1))
+
+/* extracting the seqno from buffer seqno */
+#define	SEQNO(_a)	((_a) >> IEEE80211_SEQ_SEQ_SHIFT)
+
+/*
+ * Whether the current sequence number is within the
+ * BAW.
+ */
+#define	BAW_WITHIN(_start, _bawsz, _seqno)	\
+	     ((((_seqno) - (_start)) & 4095) < (_bawsz))
+
+static struct ieee80211_tx_ampdu * ath_tx_get_tx_tid(struct ath_node *an,
+    int tid);
 static int ath_tx_ampdu_pending(struct ath_softc *sc, struct ath_node *an,
     int tid);
 static int ath_tx_ampdu_running(struct ath_softc *sc, struct ath_node *an,
@@ -946,8 +967,10 @@ ath_tx_start(struct ath_softc *sc, struc
 	is_ampdu_pending = ath_tx_ampdu_pending(sc, ATH_NODE(ni), tid);
 	is_ampdu = is_ampdu_tx | is_ampdu_pending;
 
-	DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: tid=%d, ac=%d, is_ampdu=%d\n", 
+#if 0
+	DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: tid=%d, ac=%d, is_ampdu=%d\n",
 	    __func__, tid, pri, is_ampdu);
+#endif
 
 	/* Multicast frames go onto the software multicast queue */
 	if (ismcast)
@@ -966,7 +989,7 @@ ath_tx_start(struct ath_softc *sc, struc
 	 * If needed, the sequence number has been assigned.
 	 * Squirrel it away somewhere easy to get to.
 	 */
-	bf->bf_state.bfs_seqno = M_SEQNO_GET(m0);
+	bf->bf_state.bfs_seqno = M_SEQNO_GET(m0) << IEEE80211_SEQ_SEQ_SHIFT;
 
 #if 0
 	/* Is ampdu pending? fetch the seqno and print it out */
@@ -1394,6 +1417,90 @@ ath_tx_action_frame_override_queue(struc
 /* Per-node software queue operations */
 
 /*
+ * Add the current packet to the given BAW.
+ * It is assumed that the current packet
+ *
+ * + fits inside the BAW;
+ * + already has had a sequence number allocated.
+ */
+static void
+ath_tx_addto_baw(struct ath_softc *sc, struct ath_node *an,
+    struct ath_tid *tid, struct ath_buf *bf)
+{
+	int index, cindex;
+	struct ieee80211_tx_ampdu *tap;
+
+	if (bf->bf_state.bfs_isretried)
+		return;
+
+	tap = ath_tx_get_tx_tid(an, tid->tid);
+	DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: tid=%d, seqno %d; window %d:%d\n",
+		    __func__, tid->tid, SEQNO(bf->bf_state.bfs_seqno),
+		    tap->txa_start, tap->txa_wnd);
+
+	/*
+	 * ni->ni_txseqs[] is the currently allocated seqno.
+	 * the txa state contains the current baw start.
+	 */
+ #if 0
+	DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: tap->txa_start: %d, seqno: %d\n",
+	    __func__, tap->txa_start, SEQNO(bf->bf_state.bfs_seqno));
+#endif
+	index  = ATH_BA_INDEX(tap->txa_start, SEQNO(bf->bf_state.bfs_seqno));
+	cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
+#if 0
+	DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: index=%d, cindex=%d, baw head=%d, tail=%d\n",
+	    __func__, index, cindex, tid->baw_head, tid->baw_tail);
+#endif
+
+#if 0
+	assert(tid->tx_buf[cindex] == NULL);
+#endif
+	if (tid->tx_buf[cindex] != NULL) {
+		device_printf(sc->sc_dev,
+		    "%s: ba packet dup (index=%d, cindex=%d, "
+		    "head=%d, tail=%d)\n",
+		    __func__, index, cindex, tid->baw_head, tid->baw_tail);
+	}
+	tid->tx_buf[cindex] = bf;
+
+	if (index >= ((tid->baw_tail - tid->baw_head) & (ATH_TID_MAX_BUFS - 1))) {
+		tid->baw_tail = cindex;
+		INCR(tid->baw_tail, ATH_TID_MAX_BUFS);
+	}
+}
+
+/*
+ * seq_start - left edge of BAW
+ * seq_next - current/next sequence number to allocate
+ */
+static void
+ath_tx_update_baw(struct ath_softc *sc, struct ath_node *an,
+    struct ath_tid *tid, int seqno)
+{
+	int index, cindex;
+	struct ieee80211_tx_ampdu *tap;
+
+	tap = ath_tx_get_tx_tid(an, tid->tid);
+	DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: tid=%d, baw=%d:%d, seqno=%d\n",
+	    __func__, tid->tid, tap->txa_start, tap->txa_wnd, seqno);
+
+	index  = ATH_BA_INDEX(tap->txa_start, seqno);
+	cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
+#if 0
+	DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: index=%d, cindex=%d, baw head=%d, tail=%d\n",
+	    __func__, index, cindex, tid->baw_head, tid->baw_tail);
+#endif
+
+	tid->tx_buf[cindex] = NULL;
+
+	while (tid->baw_head != tid->baw_tail && !tid->tx_buf[tid->baw_head]) {
+		INCR(tap->txa_start, IEEE80211_SEQ_RANGE);
+		INCR(tid->baw_head, ATH_TID_MAX_BUFS);
+	}
+}
+
+/*
  * Mark the current node/TID as ready to TX.
  *
  * This is done to make it easy for the software scheduler to
@@ -1463,7 +1570,8 @@ ath_tx_tid_seqno_assign(struct ath_softc
 		return -1;
 
 	/* Manually assign sequence number */
-	seqno = ni->ni_txseqs[tid]++;
+	seqno = ni->ni_txseqs[tid];
+	INCR(ni->ni_txseqs[tid], IEEE80211_SEQ_RANGE);
 	*(uint16_t *)&wh->i_seq[0] = htole16(seqno << IEEE80211_SEQ_SEQ_SHIFT);
 	M_SEQNO_SET(m0, seqno);
 
@@ -1530,7 +1638,7 @@ ath_tx_swq(struct ath_softc *sc, struct 
 void
 ath_tx_tid_init(struct ath_softc *sc, struct ath_node *an)
 {
-	int i;
+	int i, j;
 	struct ath_tid *atid;
 
 	for (i = 0; i < IEEE80211_TID_SIZE; i++) {
@@ -1538,6 +1646,11 @@ ath_tx_tid_init(struct ath_softc *sc, st
 		STAILQ_INIT(&atid->axq_q);
 		atid->tid = i;
 		atid->an = an;
+		for (j = 0; j < ATH_TID_MAX_BUFS; j++)
+			atid->tx_buf[j] = NULL;
+		atid->baw_head = atid->baw_tail = 0;
+		atid->paused = 0;
+		atid->sched = 0;
 	}
 }
 
@@ -1611,6 +1724,7 @@ ath_tx_tid_free_pkts(struct ath_softc *s
 		if (bf == NULL) {
 			break;
 		}
+		/* XXX update BAW if needed? */
 		ATH_TXQ_REMOVE_HEAD(atid, bf_list);
 		ath_tx_freebuf(sc, bf, -1);
 	}
@@ -1673,9 +1787,10 @@ ath_tx_tid_cleanup(struct ath_softc *sc,
 static void
 ath_tx_aggr_comp(struct ath_softc *sc, struct ath_buf *bf)
 {
-	/* Success? Complete */
-	ath_tx_default_comp(sc, bf);
-
+	struct ieee80211_node *ni = bf->bf_node;
+	struct ath_node *an = ATH_NODE(ni);
+	int tid = bf->bf_state.bfs_tid;
+	struct ath_tid *atid = &an->an_tid[tid];
 	/*
 	 * Not success and have retries left?
 	 *
@@ -1690,6 +1805,14 @@ ath_tx_aggr_comp(struct ath_softc *sc, s
 	 * wasn't, we send a BAR to advance the pointer to that
 	 * place.
 	 */
+
+	/* Success? Complete */
+	DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: seqno %d\n",
+	    __func__, SEQNO(bf->bf_state.bfs_seqno));
+	ath_tx_update_baw(sc, an, atid, SEQNO(bf->bf_state.bfs_seqno));
+
+	ath_tx_default_comp(sc, bf);
+	/* bf is freed at this point */
 }
 
 /*
@@ -1703,14 +1826,26 @@ ath_tx_tid_hw_queue_aggr(struct ath_soft
 	struct ath_buf *bf;
 	struct ath_txq *txq;
 	struct ath_tid *atid = &an->an_tid[tid];
+	struct ieee80211_tx_ampdu *tap;
 
 	for (;;) {
                 bf = STAILQ_FIRST(&atid->axq_q);
 		if (bf == NULL) {
 			break;
 		}
+		tap = ath_tx_get_tx_tid(an, tid);
 
 		/* XXX check if seqno is outside of BAW, if so don't queue it */
+		if (! BAW_WITHIN(tap->txa_start, tap->txa_wnd,
+		    SEQNO(bf->bf_state.bfs_seqno))) {
+			DPRINTF(sc, ATH_DEBUG_SW_TX,
+			    "%s: seq %d outside of %d/%d; waiting\n",
+			    __func__, SEQNO(bf->bf_state.bfs_seqno),
+			    tap->txa_start, tap->txa_wnd);
+			break;
+		}
+
+		ath_tx_addto_baw(sc, an, atid, bf);
 
 		/*
 		 * XXX If the seqno is out of BAW, then we should pause this TID
@@ -1825,7 +1960,7 @@ ath_tx_get_tx_tid(struct ath_node *an, i
 	int ac;
 
 	if (tid == IEEE80211_NONQOS_TID)
-		return 0;
+		return NULL;
 
 	ac = TID_TO_WME_AC(tid);
 

Modified: user/adrian/if_ath_tx/sys/dev/ath/if_athvar.h
==============================================================================
--- user/adrian/if_ath_tx/sys/dev/ath/if_athvar.h	Fri Aug  5 15:07:28 2011	(r224657)
+++ user/adrian/if_ath_tx/sys/dev/ath/if_athvar.h	Fri Aug  5 17:15:46 2011	(r224658)
@@ -113,9 +113,12 @@ struct ath_tid {
 	 * shifted the head/tail of the array are also
 	 * appropriately shifted.
 	 */
-	struct ath_buf *tx_buf[ATH_TID_MAX_BUFS];	/* active tx buffers, beginning at current BAW */
-	int			baw_head;	/* where the baw head is in the array */
-	int			baw_tail;	/* where the BAW tail is in the array */
+	/* active tx buffers, beginning at current BAW */
+	struct ath_buf		*tx_buf[ATH_TID_MAX_BUFS];
+	/* where the baw head is in the array */
+	int			baw_head;
+	/* where the BAW tail is in the array */
+	int			baw_tail;
 };
 
 /* driver-specific node state */



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