From owner-svn-src-user@FreeBSD.ORG Tue Jun 14 16:50:29 2011 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id BC77C10657D9; Tue, 14 Jun 2011 16:50:29 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id ABBC08FC12; Tue, 14 Jun 2011 16:50:29 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id p5EGoT0h043451; Tue, 14 Jun 2011 16:50:29 GMT (envelope-from adrian@svn.freebsd.org) Received: (from adrian@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id p5EGoTfA043447; Tue, 14 Jun 2011 16:50:29 GMT (envelope-from adrian@svn.freebsd.org) Message-Id: <201106141650.p5EGoTfA043447@svn.freebsd.org> From: Adrian Chadd Date: Tue, 14 Jun 2011 16:50:29 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r223087 - user/adrian/if_ath_tx/sys/dev/ath X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 14 Jun 2011 16:50:29 -0000 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,