Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 17 Aug 2011 09:44:15 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r224933 - user/adrian/if_ath_tx/sys/dev/ath
Message-ID:  <201108170944.p7H9iFR3096619@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: adrian
Date: Wed Aug 17 09:44:15 2011
New Revision: 224933
URL: http://svn.freebsd.org/changeset/base/224933

Log:
  Flesh out a completely untested aggregate completion handler.

Modified:
  user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.c
  user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.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	Wed Aug 17 09:40:52 2011	(r224932)
+++ user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.c	Wed Aug 17 09:44:15 2011	(r224933)
@@ -2344,20 +2344,28 @@ ath_tx_comp_cleanup_aggr(struct ath_soft
  * not the last descriptor in the first frame.
  */
 static void
-ath_tx_aggr_comp_aggr(struct ath_softc *sc, struct ath_buf *bf, int fail)
+ath_tx_aggr_comp_aggr(struct ath_softc *sc, struct ath_buf *bf_first, int fail)
 {
 	//struct ath_desc *ds = bf->bf_lastds;
-	struct ieee80211_node *ni = bf->bf_node;
+	struct ieee80211_node *ni = bf_first->bf_node;
 	struct ath_node *an = ATH_NODE(ni);
-	int tid = bf->bf_state.bfs_tid;
+	int tid = bf_first->bf_state.bfs_tid;
 	struct ath_tid *atid = &an->an_tid[tid];
-	struct ath_tx_status *ts = &bf->bf_status.ds_txstat;
+	struct ath_tx_status *ts = &bf_first->bf_status.ds_txstat;
+	struct ieee80211_tx_ampdu *tap;
+	ath_bufhead bf_q;
+	int seq_st, tx_ok;
+	int hasba, isaggr;
+	uint32_t ba[2];
+	struct ath_buf *bf, *bf_next;
+	int ba_index;
+	int drops = 0;
 
 	/*
 	 * Punt cleanup to the relevant function, not our problem now
 	 */
 	if (atid->cleanup_inprogress) {
-		ath_tx_comp_cleanup_aggr(sc, bf);
+		ath_tx_comp_cleanup_aggr(sc, bf_first);
 		return;
 	}
 
@@ -2365,15 +2373,83 @@ ath_tx_aggr_comp_aggr(struct ath_softc *
 	 * handle errors first
 	 */
 	if (ts->ts_status & HAL_TXERR_XRETRY) {
-		ath_tx_comp_aggr_error(sc, bf, atid);
+		ath_tx_comp_aggr_error(sc, bf_first, atid);
 		return;
 	}
 
+	STAILQ_INIT(&bf_q);
+	tap = ath_tx_get_tx_tid(an, tid);
+
 	/*
 	 * 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);
+	isaggr = bf_first->bf_state.bfs_aggr;
+	ba[0] = ts->ts_ba_low;
+	ba[1] = ts->ts_ba_high;
+
+	/* Occasionally, the MAC sends a tx status for the wrong TID. */
+	if (tid != ts->ts_tid) {
+		device_printf(sc->sc_dev, "%s: tid %d != hw tid %d\n",
+		    __func__, tid, ts->ts_tid);
+		tx_ok = 0;
+	}
+
+	/* AR5416 BA bug; this requires an interface reset */
+	/* XXX TODO */
+
+	/*
+	 * Walk the list of frames, figure out which ones were correctly
+	 * sent and which weren't.
+	 */
+	bf = bf_first;
 
-	/* AR5416 BA bug; this requires re-TX of all frames */
+	while (bf) {
+		ba_index = ATH_BA_INDEX(seq_st, SEQNO(bf->bf_state.bfs_seqno));
+		bf_next = bf->bf_next;
+
+		if (tx_ok && ATH_BA_ISSET(ba, ba_index)) {
+			ath_tx_update_baw(sc, an, atid,
+			    SEQNO(bf->bf_state.bfs_seqno));
+			ath_tx_default_comp(sc, bf, 0);
+		} else {
+			drops += ath_tx_retry_subframe(sc, bf, &bf_q);
+		}
+		bf = bf_next;
+	}
+
+	/* update rate control module about aggregate status */
+	/* XXX TODO */
+
+	/*
+	 * send bar if we dropped any frames
+	 */
+	if (drops) {
+		if (ieee80211_send_bar(ni, tap, ni->ni_txseqs[tid]) == 0) {
+			/*
+			 * Pause the TID if this was successful.
+			 * An un-successful BAR TX would never call
+			 * the BAR complete / timeout methods.
+			 */
+			ath_tx_tid_pause(sc, atid);
+		} else {
+			/* BAR TX failed */
+			device_printf(sc->sc_dev,
+			    "%s: TID %d: BAR TX failed\n",
+			    __func__, tid);
+		}
+	}
+
+	/* Prepend all frames to the beginning of the queue */
+	ATH_TXQ_LOCK(atid);
+	while ((bf = STAILQ_FIRST(&bf_q)) != NULL) {
+		ATH_TXQ_INSERT_HEAD(atid, bf, bf_list);
+		STAILQ_REMOVE_HEAD(&bf_q, bf_list);
+	}
+	ATH_TXQ_UNLOCK(atid);
 }
 
 /*

Modified: user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.h
==============================================================================
--- user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.h	Wed Aug 17 09:40:52 2011	(r224932)
+++ user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.h	Wed Aug 17 09:44:15 2011	(r224933)
@@ -40,6 +40,17 @@
  */
 #define	ATH_BA_INDEX(_st, _seq)	(((_seq) - (_st)) & (IEEE80211_SEQ_RANGE - 1))
 
+#define	WME_BA_BMP_SIZE	64
+#define	WME_MAX_BA	WME_BA_BMP_SIZE
+
+/*
+ * return whether a bit at index _n in bitmap _bm is set
+ * _sz is the size of the bitmap
+ */
+#define	ATH_BA_ISSET(_bm, _n)	(((_n) < (WME_BA_BMP_SIZE)) &&		\
+	    ((_bm)[(_n) >> 5] & (1 << ((_n) & 31))))
+
+
 /* extracting the seqno from buffer seqno */
 #define	SEQNO(_a)	((_a) >> IEEE80211_SEQ_SEQ_SHIFT)
 



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