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

Adrian Chadd adrian at FreeBSD.org
Tue Jun 14 16:50:29 UTC 2011


Author: adrian
Date: Tue Jun 14 16:50:29 2011
New Revision: 223087
URL: http://svn.freebsd.org/changeset/base/223087

Log:
  Begin making ampdu tx work (but only with non-aggregate packets.)
  
  * the TID lookup using ieee80211_gettid() was wrong, instead use the
    AC from the mbuf and convert that to a TID.
  * Since A-MPDU TX packets aren't supposed to be stuffed on the cabq
    when the station is in PS mode, don't do that. Instead, we'll eventually
    handle this lter.
  * Move the eventual TXQ selection out to ath_tx_start().
  * write a function to assign seqno's to A-MPDU TX frames.
  
  This works enough to TX non-aggregate frame in A-MPDU but it's missing
  a lot of support. In particular, BAR's aren't sent when the window needs
  shifting (because of a TX failure) and there's currently no logic to
  only queue frames which fit inside the BA window.
  
  There's also a problem with the initial sequence numbers used just after
  the ADDBA exchange, so there's a (large) BA window shift. That needs to be
  fixed.

Modified:
  user/adrian/if_ath_tx/sys/dev/ath/if_ath_debug.h
  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_debug.h
==============================================================================
--- user/adrian/if_ath_tx/sys/dev/ath/if_ath_debug.h	Tue Jun 14 16:50:16 2011	(r223086)
+++ user/adrian/if_ath_tx/sys/dev/ath/if_ath_debug.h	Tue Jun 14 16:50:29 2011	(r223087)
@@ -57,6 +57,7 @@ enum { 
 	ATH_DEBUG_TDMA		= 0x00800000,	/* TDMA processing */
 	ATH_DEBUG_TDMA_TIMER	= 0x01000000,	/* TDMA timer processing */
 	ATH_DEBUG_REGDOMAIN	= 0x02000000,	/* regulatory processing */
+	ATH_DEBUG_SW_TX		= 0x04000000,
 	ATH_DEBUG_FATAL		= 0x80000000,	/* fatal errors */
 	ATH_DEBUG_ANY		= 0xffffffff
 };

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	Tue Jun 14 16:50:16 2011	(r223086)
+++ user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.c	Tue Jun 14 16:50:29 2011	(r223087)
@@ -102,10 +102,10 @@ __FBSDID("$FreeBSD$");
 
 static int ath_tx_ampdu_pending(struct ath_softc *sc, struct ath_node *an,
     int tid);
-#if 0
 static int ath_tx_ampdu_running(struct ath_softc *sc, struct ath_node *an,
     int tid);
-#endif
+static ieee80211_seq ath_tx_tid_seqno_assign(struct ath_softc *sc,
+    struct ieee80211_node *ni, struct ath_buf *bf, struct mbuf *m0);
 
 /*
  * Whether to use the 11n rate scenario functions or not
@@ -922,21 +922,39 @@ ath_tx_start(struct ath_softc *sc, struc
 	struct ath_vap *avp = ATH_VAP(vap);
 	int r;
 	u_int pri;
+	int tid;
 	struct ath_txq *txq;
 	int ismcast;
 	const struct ieee80211_frame *wh;
+	int is_ampdu = 0;
 
 	/* Determine the target hardware queue! */
 	pri = M_WME_GETAC(m0);			/* honor classification */
+	tid = WME_AC_TO_TID(pri);
 	txq = sc->sc_ac2q[pri];
 	wh = mtod(m0, struct ieee80211_frame *);
 	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
 
-	/* Multicast frames go onto the software multicat queue */
-	if (ismcast && (vap->iv_ps_sta || avp->av_mcastq.axq_depth))
+	/* A-MPDU TX */
+	if ((ath_tx_ampdu_running(sc, ATH_NODE(ni), tid)) ||
+	    (ath_tx_ampdu_pending(sc, ATH_NODE(ni), tid)))
+		is_ampdu = 1;
+
+	DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: tid=%d, ac=%d, is_ampdu=%d\n", 
+	    __func__, tid, pri, is_ampdu);
+
+	/* Multicast frames go onto the software multicast queue */
+	if (ismcast)
+		txq = &avp->av_mcastq;
+ 	if ((! is_ampdu) && (vap->iv_ps_sta || avp->av_mcastq.axq_depth))
 		txq = &avp->av_mcastq;
 
 	/* Do the generic frame setup */
+
+	/* A-MPDU TX? Manually set sequence number */
+	if (is_ampdu)
+		(void) ath_tx_tid_seqno_assign(sc, ni, bf, m0);
+
 	/* This also sets up the DMA map */
 	r = ath_tx_normal_setup(sc, ni, bf, m0);
 
@@ -951,7 +969,7 @@ ath_tx_start(struct ath_softc *sc, struc
 
 #if 1
 	/* add to software queue */
-	ath_tx_swq(sc, ni, bf, m0);
+	ath_tx_swq(sc, ni, txq, bf, m0);
 #else
 
 	/*
@@ -1270,37 +1288,56 @@ ath_tx_node_unsched(struct ath_softc *sc
 }
 
 /*
+ * Assign a sequence number manually to the given frame.
+ * 
+ * This should only be called for A-MPDU TX frames. 
+ */
+static ieee80211_seq
+ath_tx_tid_seqno_assign(struct ath_softc *sc, struct ieee80211_node *ni,
+    struct ath_buf *bf, struct mbuf *m0)
+{
+	struct ieee80211_frame *wh;
+	int tid, pri;
+	ieee80211_seq seqno;
+
+	/* TID lookup */
+	wh = mtod(m0, struct ieee80211_frame *);
+	pri = M_WME_GETAC(m0);			/* honor classification */
+	tid = WME_AC_TO_TID(pri);
+
+	/* Does the packet require a sequence number? */
+	if (! IEEE80211_QOS_HAS_SEQ(wh))
+		return -1;
+
+	/* Manually assign sequence number */
+	seqno = ni->ni_txseqs[tid]++;
+	*(uint16_t *)&wh->i_seq[0] = htole16(seqno << IEEE80211_SEQ_SEQ_SHIFT);
+	M_SEQNO_SET(m0, seqno);
+
+	/* Return so caller can do something with it if needed */
+	return seqno;
+}
+
+
+/*
  * Queue the given packet on the relevant software queue.
  *
  * This however doesn't queue the packet to the hardware!
  */
 void
-ath_tx_swq(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf,
-    struct mbuf *m0)
+ath_tx_swq(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_txq *txq,
+    struct ath_buf *bf, struct mbuf *m0)
 {
 	struct ath_node *an = ATH_NODE(ni);
-	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211_frame *wh;
-	struct ath_vap *avp = ATH_VAP(vap);
 	struct ath_tid *atid;
-	struct ath_txq *txq;	/* eventual destination queue */
-	int tid;
-	int ismcast;
-	u_int pri;
+	int pri, tid;
 
 	/* Fetch the TID - non-QoS frames get assigned to TID 16 */
 	wh = mtod(m0, struct ieee80211_frame *);
-	tid = ieee80211_gettid(wh);
-	atid = &an->an_tid[tid];
-
-	/* Fetch the eventual destination queue */
 	pri = M_WME_GETAC(m0);			/* honor classification */
-	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
-	txq = sc->sc_ac2q[pri];
-
-	/* Handle mcast, or PS STA */
-	if (ismcast && (vap->iv_ps_sta || avp->av_mcastq.axq_depth))
-		txq = &avp->av_mcastq;
+	tid = WME_AC_TO_TID(pri);
+	atid = &an->an_tid[tid];
 
 	/* Set local packet state, used to queue packets to hardware */
 	bf->bf_state.bfs_tid = tid;
@@ -1311,7 +1348,6 @@ ath_tx_swq(struct ath_softc *sc, struct 
 	ATH_TXQ_INSERT_TAIL(atid, bf, bf_list);
 	ATH_TXQ_UNLOCK(atid);
 
-
 	/*
 	 * ATH_TXNODE must be acquired before ATH_NODE is acquired
 	 * if they're both needed.
@@ -1605,7 +1641,6 @@ ath_tx_get_tx_tid(struct ath_node *an, i
 	return tap;
 }
 
-#if 0
 /*
  * Is AMPDU-TX running?
  *
@@ -1616,15 +1651,14 @@ ath_tx_ampdu_running(struct ath_softc *s
 {
 	struct ieee80211_tx_ampdu *tap;
 
-	ATH_NODE_LOCK_ASSERT(an);
+	//ATH_NODE_LOCK_ASSERT(an);
 
 	tap = ath_tx_get_tx_tid(an, tid);
 	if (tap == NULL)
 		return 0;	/* Not valid; default to not running */
 
-	return (tap->txa_flags & IEEE80211_AGGR_RUNNING);
+	return !! (tap->txa_flags & IEEE80211_AGGR_RUNNING);
 }
-#endif
 
 /*
  * Is AMPDU-TX negotiation pending?
@@ -1636,13 +1670,13 @@ ath_tx_ampdu_pending(struct ath_softc *s
 {
 	struct ieee80211_tx_ampdu *tap;
 
-	ATH_NODE_LOCK_ASSERT(an);
+	//ATH_NODE_LOCK_ASSERT(an);
 
 	tap = ath_tx_get_tx_tid(an, tid);
 	if (tap == NULL)
 		return 0;	/* Not valid; default to not pending */
 
-	return (tap->txa_flags & IEEE80211_AGGR_XCHGPEND);
+	return !! (tap->txa_flags & IEEE80211_AGGR_XCHGPEND);
 }
 
 

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	Tue Jun 14 16:50:16 2011	(r223086)
+++ user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.h	Tue Jun 14 16:50:29 2011	(r223087)
@@ -44,7 +44,7 @@ extern int ath_raw_xmit(struct ieee80211
 
 /* software queue stuff */
 extern void ath_tx_swq(struct ath_softc *sc, struct ieee80211_node *ni,
-    struct ath_buf *bf, struct mbuf *m0);
+    struct ath_txq *txq, struct ath_buf *bf, struct mbuf *m0);
 extern void ath_tx_tid_init(struct ath_softc *sc, struct ath_node *an);
 extern void ath_tx_tid_cleanup(struct ath_softc *sc, struct ath_node *an);
 extern void ath_tx_tid_hw_queue(struct ath_softc *sc, struct ath_node *an,


More information about the svn-src-user mailing list