svn commit: r225021 - user/adrian/if_ath_tx/sys/dev/ath

Adrian Chadd adrian at FreeBSD.org
Sat Aug 20 06:08:31 UTC 2011


Author: adrian
Date: Sat Aug 20 06:08:31 2011
New Revision: 225021
URL: http://svn.freebsd.org/changeset/base/225021

Log:
  Another combined diff - partly debugging, partly implementing more
  aggregation related stuff.
  
  Debugging/enforcing (which I'll likely remove at some point, or at
  least make optional):
  
  * Remove ath_buf's from the aggregate list - ie, blank bf->bf_next -
    when they've been handled and they're being requeued or completed.
  
  * Print out a message ath_tx_default_comp() if the ath_buf in question
    is still on an aggregation list.
  
  * Check whether the number of buffers handled in the aggregate frame
    completion or aggregate frame error functions match the number of
    frames -in- the aggregate buffer list. Print out an error if this
    isn't the case.
  
  Aggregation changes:
  
  * Fill out the rest of the ath_rc_series fields in the ath_buf -
    max4msframelen and the flags fields. This is done after the
    rate control decisions have been made in the (raw, normal) TX
    path. Later on, this will be pushed into the rate control module
    and then, much later on, it'll be pushed into net80211.
  
  * Implement the rest of the ampdu delimiter calculation code.
    The ampdu density figure, negotiated in STA mode and configured
    in hostap mode, is enforced when calculating delimiter counts.
    It uses the "fastest" rate (ie, the first one) to calculate
    how long a frame will be (in bytes) at the given rate/config,
    and then enforces that the configured delimiter count matches
    at least -that- length. If a sub-frame length is smaller than
    the configured mpdudensity, the delimiter count is the
    minimum density, rather than soley based on the frame count.
  
  * Implement a very simple function to return the maximum frame length
    for 4ms, based on the slowest rate. If the rate control returns
    a set of rate series rather than a single one, the aggregate may
    end up being transmitted at the slowest rather than the fastest.
  
  A lot of stuff that has been shoehorned into if_ath_tx_ht.c should
  likely live elsewhere, including the HAL and net80211. I'll worry
  about where to place all of this once the code is (more) stable.
  
  Obtained from:	Atheros, Linux ath9k

Modified:
  user/adrian/if_ath_tx/sys/dev/ath/README
  user/adrian/if_ath_tx/sys/dev/ath/if_ath.c
  user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.c
  user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.h
  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.h
  user/adrian/if_ath_tx/sys/dev/ath/if_athrate.h

Modified: user/adrian/if_ath_tx/sys/dev/ath/README
==============================================================================
--- user/adrian/if_ath_tx/sys/dev/ath/README	Fri Aug 19 21:59:47 2011	(r225020)
+++ user/adrian/if_ath_tx/sys/dev/ath/README	Sat Aug 20 06:08:31 2011	(r225021)
@@ -1,3 +1,18 @@
+Things to debug!
+
+* Write something in ath_tx_default_comp() that ensures the buffer is unlinked
+  (ie, not part of an aggregate)
+
+* Write something in the aggr comp function which checks that the number of
+  frames in the aggregate list matches bf_stats.bfs_nframes
+  - Done
+
+* Am I losing an ath_buf in the hardware TX queue code? Ie, are they not
+  ever queued?
+
+* Is it some missing sequence numbers? ie, is addto_baw being called with
+  sequence numbers out of order, or "gaps" in the sequence numbers?
+
 Things that need doing!
 
 * RIFS? Do I care about supporting RIFS?

Modified: user/adrian/if_ath_tx/sys/dev/ath/if_ath.c
==============================================================================
--- user/adrian/if_ath_tx/sys/dev/ath/if_ath.c	Fri Aug 19 21:59:47 2011	(r225020)
+++ user/adrian/if_ath_tx/sys/dev/ath/if_ath.c	Sat Aug 20 06:08:31 2011	(r225021)
@@ -4159,6 +4159,9 @@ ath_tx_default_comp(struct ath_softc *sc
 	if (bf->bf_state.bfs_dobaw)
 		device_printf(sc->sc_dev,
 		    "%s: dobaw should've been cleared!\n", __func__);
+	if (bf->bf_next != NULL)
+		device_printf(sc->sc_dev,
+		    "%s: bf_next not NULL!\n", __func__);
 
 	/*
 	 * Do any tx complete callback.  Note this must

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 19 21:59:47 2011	(r225020)
+++ user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.c	Sat Aug 20 06:08:31 2011	(r225021)
@@ -1273,6 +1273,12 @@ ath_tx_start(struct ath_softc *sc, struc
 	/* At this point m0 could have changed! */
 	m0 = bf->bf_m;
 
+	/*
+	 * ath_tx_normal_setup() has done the single and multi-rate
+	 * retry rate lookup for us. Fill in the rcflags based on
+	 * that.
+	 */
+	ath_tx_rate_fill_rcflags(sc, bf);
 #if 1
 	/*
 	 * If it's a multicast frame, do a direct-dispatch to the
@@ -1510,6 +1516,11 @@ ath_tx_raw_start(struct ath_softc *sc, s
 		bf->bf_state.bfs_rc[2].tries = params->ibp_try2;
 		bf->bf_state.bfs_rc[3].tries = params->ibp_try3;
 	}
+	/*
+	 * All the required rate control decisions have been made;
+	 * fill in the rc flags.
+	 */
+	ath_tx_rate_fill_rcflags(sc, bf);
 
 	/* NB: no buffered multicast in power save support */
 
@@ -2478,6 +2489,7 @@ ath_tx_comp_aggr_error(struct ath_softc 
 	bf = bf_first;
 	while (bf) {
 		bf_next = bf->bf_next;
+		bf->bf_next = NULL;	/* Remove it from the aggr list */
 		drops += ath_tx_retry_subframe(sc, bf, &bf_q);
 		bf = bf_next;
 	}
@@ -2540,6 +2552,7 @@ ath_tx_comp_cleanup_aggr(struct ath_soft
 	while (bf) {
 		atid->incomp--;
 		bf_next = bf->bf_next;
+		bf->bf_next = NULL;	/* Remove it from the aggr list */
 		ath_tx_default_comp(sc, bf, -1);
 		bf = bf_next;
 	}
@@ -2580,6 +2593,7 @@ 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;
 
 	DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR, "%s: called\n", __func__);
 
@@ -2635,8 +2649,10 @@ ath_tx_aggr_comp_aggr(struct ath_softc *
 	bf = bf_first;
 
 	while (bf) {
+		np++;
 		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 */
 
 		DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
 		    "%s: checking bf=%p seqno=%d; ack=%d\n",
@@ -2656,6 +2672,10 @@ ath_tx_aggr_comp_aggr(struct ath_softc *
 		bf = bf_next;
 	}
 
+	if (np != 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);
+
 	/* update rate control module about aggregate status */
 	/* XXX TODO */
 

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	Fri Aug 19 21:59:47 2011	(r225020)
+++ user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.h	Sat Aug 20 06:08:31 2011	(r225021)
@@ -44,6 +44,11 @@
 #define	WME_MAX_BA	WME_BA_BMP_SIZE
 
 /*
+ * How 'busy' to try and keep the hardware txq
+ */
+#define	ATH_AGGR_MIN_QDEPTH		2
+
+/*
  * return whether a bit at index _n in bitmap _bm is set
  * _sz is the size of the bitmap
  */

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	Fri Aug 19 21:59:47 2011	(r225020)
+++ user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx_ht.c	Sat Aug 20 06:08:31 2011	(r225021)
@@ -88,6 +88,8 @@ __FBSDID("$FreeBSD$");
 
 #include <dev/ath/if_ath_tx.h>		/* XXX for some support functions */
 #include <dev/ath/if_ath_tx_ht.h>
+#include <dev/ath/if_athrate.h>
+#include <dev/ath/if_ath_debug.h>
 
 /*
  * XXX net80211?
@@ -135,19 +137,196 @@ int ath_max_4ms_framelen[4][32] = {
 };
 
 /*
+ * XXX should be in net80211
+ */
+static int ieee80211_mpdudensity_map[] = {
+	0,		/* IEEE80211_HTCAP_MPDUDENSITY_NA */
+	25,		/* IEEE80211_HTCAP_MPDUDENSITY_025 */
+	50,		/* IEEE80211_HTCAP_MPDUDENSITY_05 */
+	100,		/* IEEE80211_HTCAP_MPDUDENSITY_1 */
+	200,		/* IEEE80211_HTCAP_MPDUDENSITY_2 */
+	400,		/* IEEE80211_HTCAP_MPDUDENSITY_4 */
+	800,		/* IEEE80211_HTCAP_MPDUDENSITY_8 */
+	1600,		/* IEEE80211_HTCAP_MPDUDENSITY_16 */
+};
+
+/*
+ * XXX should be in the HAL/net80211 ?
+ */
+#define	BITS_PER_BYTE		8
+#define	OFDM_PLCP_BITS		22
+#define	HT_RC_2_MCS(_rc)	((_rc) & 0x7f)
+#define	HT_RC_2_STREAMS(_rc)	((((_rc) & 0x78) >> 3) + 1)
+#define	L_STF			8
+#define	L_LTF			8
+#define	L_SIG			4
+#define	HT_SIG			8
+#define	HT_STF			4
+#define	HT_LTF(_ns)		(4 * (_ns))
+#define	SYMBOL_TIME(_ns)	((_ns) << 2)		// ns * 4 us
+#define	SYMBOL_TIME_HALFGI(_ns)	(((_ns) * 18 + 4) / 5)	// ns * 3.6 us
+#define	NUM_SYMBOLS_PER_USEC(_usec)	(_usec >> 2)
+#define	NUM_SYMBOLS_PER_USEC_HALFGI(_usec)	(((_usec*5)-4)/18)
+#define	IS_HT_RATE(_rate)	((_rate) & 0x80)
+
+const uint32_t bits_per_symbol[][2] = {
+    /* 20MHz 40MHz */
+    {    26,   54 },     //  0: BPSK
+    {    52,  108 },     //  1: QPSK 1/2
+    {    78,  162 },     //  2: QPSK 3/4
+    {   104,  216 },     //  3: 16-QAM 1/2
+    {   156,  324 },     //  4: 16-QAM 3/4
+    {   208,  432 },     //  5: 64-QAM 2/3
+    {   234,  486 },     //  6: 64-QAM 3/4
+    {   260,  540 },     //  7: 64-QAM 5/6
+    {    52,  108 },     //  8: BPSK
+    {   104,  216 },     //  9: QPSK 1/2
+    {   156,  324 },     // 10: QPSK 3/4
+    {   208,  432 },     // 11: 16-QAM 1/2
+    {   312,  648 },     // 12: 16-QAM 3/4
+    {   416,  864 },     // 13: 64-QAM 2/3
+    {   468,  972 },     // 14: 64-QAM 3/4
+    {   520, 1080 },     // 15: 64-QAM 5/6
+    {    78,  162 },     // 16: BPSK
+    {   156,  324 },     // 17: QPSK 1/2
+    {   234,  486 },     // 18: QPSK 3/4
+    {   312,  648 },     // 19: 16-QAM 1/2
+    {   468,  972 },     // 20: 16-QAM 3/4
+    {   624, 1296 },     // 21: 64-QAM 2/3
+    {   702, 1458 },     // 22: 64-QAM 3/4
+    {   780, 1620 },     // 23: 64-QAM 5/6
+    {   104,  216 },     // 24: BPSK
+    {   208,  432 },     // 25: QPSK 1/2
+    {   312,  648 },     // 26: QPSK 3/4
+    {   416,  864 },     // 27: 16-QAM 1/2
+    {   624, 1296 },     // 28: 16-QAM 3/4
+    {   832, 1728 },     // 29: 64-QAM 2/3
+    {   936, 1944 },     // 30: 64-QAM 3/4
+    {  1040, 2160 },     // 31: 64-QAM 5/6
+};
+
+/*
+ * Fill in the rate array information based on the current
+ * node configuration and the choices made by the rate
+ * selection code and ath_buf setup code.
+ *
+ * Later on, this may end up also being made by the
+ * rate control code, but for now it can live here.
+ *
+ * This needs to be called just before the packet is
+ * queued to the software queue or hardware queue,
+ * so all of the needed fields in bf_state are setup.
+ */
+void
+ath_tx_rate_fill_rcflags(struct ath_softc *sc, struct ath_buf *bf)
+{
+	struct ieee80211_node *ni = bf->bf_node;
+	struct ieee80211com *ic = ni->ni_ic;
+	const HAL_RATE_TABLE *rt = sc->sc_currates;
+	struct ath_rc_series *rc = bf->bf_state.bfs_rc;
+	uint8_t rate;
+	int i;
+
+	for (i = 0; i < ATH_RC_NUM; i++) {
+		rc[i].flags = 0;
+		if (rc[i].tries == 0)
+			continue;
+
+		rate = rt->info[rc[i].rix].rateCode;
+
+		if (bf->bf_state.bfs_flags &
+		    (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA))
+			rc[i].flags |= ATH_RC_RTSCTS_FLAG;
+
+		/* Only enable shortgi, 2040, dual-stream if HT is set */
+		if (IS_HT_RATE(rate)) {
+			rc[i].flags |= ATH_RC_HT_FLAG;
+
+			if (ni->ni_chw == 40)
+				rc[i].flags |= ATH_RC_CW40_FLAG;
+
+			if (ni->ni_chw == 40 &&
+			    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 &&
+			    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40)
+				rc[i].flags |= ATH_RC_SGI_FLAG;
+
+			if (ni->ni_chw == 20 &&
+			    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 &&
+			    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20)
+				rc[i].flags |= ATH_RC_SGI_FLAG;
+
+			/* XXX dual stream? and 3-stream? */
+		}
+
+		/*
+		 * Calculate the maximum 4ms frame length based
+		 * on the MCS rate, SGI and channel width flags.
+		 */
+		if ((rc[i].flags & ATH_RC_HT_FLAG) &&
+		    (HT_RC_2_MCS(rate) < 32)) {
+			int j;
+			if (rc[i].flags & ATH_RC_CW40_FLAG) {
+				if (rc[i].flags & ATH_RC_SGI_FLAG)
+					j = MCS_HT40_SGI;
+				else
+					j = MCS_HT40;
+			} else {
+				if (rc[i].flags & ATH_RC_SGI_FLAG)
+					j = MCS_HT20_SGI;
+				else
+					j = MCS_HT20;
+			}
+			rc[i].max4msframelen =
+			    ath_max_4ms_framelen[j][HT_RC_2_MCS(rate)];
+		} else
+			rc[i].max4msframelen = 0;
+#if 0
+		DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
+		    "%s: i=%d, rate=0x%x, flags=0x%x, max4ms=%d\n",
+		    __func__, i, rate, rc[i].flags, rc[i].max4msframelen);
+#endif
+	}
+}
+
+/*
  * Return the number of delimiters to be added to
  * meet the minimum required mpdudensity.
+ *
  * Caller should make sure that the rate is HT.
  *
  * TODO: is this delimiter calculation supposed to be the
  * total frame length, the hdr length, the data length (including
  * delimiters, padding, CRC, etc) or ?
+ *
+ * TODO: this should ensure that the rate control information
+ * HAS been setup for the first rate.
+ *
+ * TODO: ensure this is only called for MCS rates.
+ *
+ * TODO: enforce MCS < 31
  */
 static int
 ath_compute_num_delims(struct ath_softc *sc, struct ath_buf *first_bf,
     uint16_t pktlen)
 {
-	int ndelim;
+	const HAL_RATE_TABLE *rt = sc->sc_currates;
+	struct ieee80211_node *ni = first_bf->bf_node;
+	struct ieee80211vap *vap = ni->ni_vap;
+	int ndelim, mindelim = 0;
+	int mpdudensity;	 /* in 1/100'th of a microsecond */
+	uint8_t rc, rix, flags;
+	int width, half_gi;
+	uint32_t nsymbits, nsymbols;
+	uint16_t minlen;
+
+	/*
+	 * vap->iv_ampdu_density is a value, rather than the actual
+	 * density.
+	 */
+	if (vap->iv_ampdu_density > IEEE80211_HTCAP_MPDUDENSITY_16)
+		mpdudensity = 1600;		/* maximum density */
+	else
+		mpdudensity = ieee80211_mpdudensity_map[vap->iv_ampdu_density];
 
 	/* Select standard number of delimiters based on frame length */
 	ndelim = ATH_AGGR_GET_NDELIM(pktlen);
@@ -160,19 +339,85 @@ ath_compute_num_delims(struct ath_softc 
 	 */
 	ndelim += ATH_AGGR_ENCRYPTDELIM;
 
+	DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
+	    "%s: pktlen=%d, ndelim=%d, mpdudensity=%d\n",
+	    __func__, pktlen, ndelim, mpdudensity);
+
 	/*
 	 * If the MPDU density is 0, we can return here.
 	 * Otherwise, we need to convert the desired mpdudensity
 	 * into a byte length, based on the rate in the subframe.
-	 *
-	 * XXX TODO: since the rate scenario hasn't been configured
-	 * XXX yet, this is likely not going to work. So, for now,
-	 * XXX ignore it.
 	 */
+	if (mpdudensity == 0)
+		return ndelim;
+
+	/*
+	 * Convert desired mpdu density from microeconds to bytes based
+	 * on highest rate in rate series (i.e. first rate) to determine
+	 * required minimum length for subframe. Take into account
+	 * whether high rate is 20 or 40Mhz and half or full GI.
+	 */
+	rix = first_bf->bf_state.bfs_rc[0].rix;
+	rc = rt->info[rix].rateCode;
+	flags = first_bf->bf_state.bfs_rc[0].flags;
+	width = !! (flags & ATH_RC_CW40_FLAG);
+	half_gi = !! (flags & ATH_RC_SGI_FLAG);
+
+	/*
+	 * mpdudensity is in 1/100th of a usec, so divide by 100
+	 */
+	if (half_gi)
+		nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(mpdudensity);
+	else
+		nsymbols = NUM_SYMBOLS_PER_USEC(mpdudensity);
+	nsymbols /= 100;
+
+	if (nsymbols == 0)
+		nsymbols = 1;
+
+	nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width];
+	minlen = (nsymbols * nsymbits) / BITS_PER_BYTE;
+
+	/*
+	 * Min length is the minimum frame length for the
+	 * required MPDU density.
+	 */
+	if (pktlen < minlen) {
+		mindelim = (minlen - pktlen) / ATH_AGGR_DELIM_SZ;
+		ndelim = MAX(mindelim, ndelim);
+	}
+
+	DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
+	    "%s: pktlen=%d, minlen=%d, rix=%x, rc=%x, width=%d, hgi=%d, ndelim=%d\n",
+	    __func__, pktlen, minlen, rix, rc, width, half_gi, ndelim);
+
 	return ndelim;
 }
 
 /*
+ * Fetch the aggregation limit.
+ *
+ * It's the lowest of the four rate series 4ms frame length.
+ */
+static int
+ath_get_aggr_limit(struct ath_softc *sc, struct ath_buf *bf)
+{
+	int amin = 65530;
+	int i;
+
+	for (i = 0; i < 4; i++) {
+		if (bf->bf_state.bfs_rc[i].tries == 0)
+			continue;
+		amin = MIN(amin, bf->bf_state.bfs_rc[i].max4msframelen);
+	}
+
+	DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR, "%s: max frame len= %d\n",
+	    __func__, amin);
+
+	return amin;
+}
+
+/*
  * Setup a 11n rate series structure
  *
  * This should be called for both legacy and MCS rates.
@@ -207,6 +452,10 @@ ath_rateseries_setup(struct ath_softc *s
 	else
 		pktlen = bf->bf_state.bfs_pktlen;
 
+	/*
+	 * XXX TODO: modify this routine to use the bfs_rc[x].flags
+	 * XXX fields.
+	 */
 	memset(series, 0, sizeof(HAL_11N_RATE_SERIES) * 4);
 	for (i = 0; i < 4;  i++) {
 		/* Only set flags for actual TX attempts */
@@ -403,12 +652,6 @@ ath_tx_form_aggr(struct ath_softc *sc, s
 
 	h_baw = tap->txa_wnd / 2;
 
-	/* Calculate aggregation limit */
-	/*
-	 * XXX TODO: do not exceed 4ms packet length
-	 */
-	aggr_limit = 65530;		/* XXX just for now, for testing */
-
 	for (;;) {
 		ATH_TXQ_LOCK(tid);
 		bf = TAILQ_FIRST(&tid->axq_q);
@@ -418,6 +661,13 @@ ath_tx_form_aggr(struct ath_softc *sc, s
 			ATH_TXQ_UNLOCK(tid);
 			status = ATH_AGGR_DONE;
 			break;
+		} else {
+			/*
+			 * It's the first frame;
+			 * set the aggregation limit based on the
+			 * rate control decision that has been made.
+			 */
+			aggr_limit = ath_get_aggr_limit(sc, bf_first);
 		}
 
 		/* Set this early just so things don't get confused */
@@ -442,6 +692,13 @@ ath_tx_form_aggr(struct ath_softc *sc, s
 		}
 
 		/*
+		 * If any of the rates are non-HT, this packet
+		 * can't be aggregated.
+		 * XXX TODO: add a bf_state flag which gets marked
+		 * if any active rate is non-HT.
+		 */
+
+		/*
 		 * If the packet has a sequence number, do not
 		 * step outside of the block-ack window.
 		 */
@@ -481,7 +738,6 @@ ath_tx_form_aggr(struct ath_softc *sc, s
 			break;
 		}
 
-
 		/*
 		 * this packet is part of an aggregate.
 		 */

Modified: user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx_ht.h
==============================================================================
--- user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx_ht.h	Fri Aug 19 21:59:47 2011	(r225020)
+++ user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx_ht.h	Sat Aug 20 06:08:31 2011	(r225021)
@@ -50,6 +50,8 @@ typedef enum {
 
 extern int	ath_max_4ms_framelen[4][32];
 
+extern void ath_tx_rate_fill_rcflags(struct ath_softc *sc, struct ath_buf *bf);
+
 extern void	ath_buf_set_rate(struct ath_softc *sc,
 		struct ieee80211_node *ni, struct ath_buf *bf);
 

Modified: user/adrian/if_ath_tx/sys/dev/ath/if_athrate.h
==============================================================================
--- user/adrian/if_ath_tx/sys/dev/ath/if_athrate.h	Fri Aug 19 21:59:47 2011	(r225020)
+++ user/adrian/if_ath_tx/sys/dev/ath/if_athrate.h	Sat Aug 20 06:08:31 2011	(r225021)
@@ -79,6 +79,12 @@ void	ath_rate_detach(struct ath_ratectrl
 
 #define	ATH_RC_NUM		4
 
+#define	ATH_RC_DS_FLAG		0x01	/* dual-stream rate */
+#define	ATH_RC_CW40_FLAG	0x02	/* use HT40 */
+#define	ATH_RC_SGI_FLAG		0x04	/* use short-GI */
+#define	ATH_RC_HT_FLAG		0x08	/* use HT */
+#define	ATH_RC_RTSCTS_FLAG	0x10	/* enable RTS/CTS protection */
+
 struct ath_rc_series {
 	uint8_t rix;		/* ratetable index, not rate code */
 	uint8_t tries;


More information about the svn-src-user mailing list