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