Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 29 Jan 2011 11:35:23 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r218065 - in head/sys: conf dev/ath modules/ath
Message-ID:  <201101291135.p0TBZNqf030328@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: adrian
Date: Sat Jan 29 11:35:23 2011
New Revision: 218065
URL: http://svn.freebsd.org/changeset/base/218065

Log:
  Migrate the TX path code out of if_ath and into a separate source file.
  
  There's two reasons for this:
  
  * the raw and non-raw TX path shares a lot of duplicate code which should be
    refactored;
  * the 11n-ready chip TX path needs a little reworking.

Added:
  head/sys/dev/ath/if_ath_misc.h   (contents, props changed)
  head/sys/dev/ath/if_ath_tx.c   (contents, props changed)
  head/sys/dev/ath/if_ath_tx.h   (contents, props changed)
Modified:
  head/sys/conf/files
  head/sys/dev/ath/if_ath.c
  head/sys/modules/ath/Makefile

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files	Sat Jan 29 10:32:00 2011	(r218064)
+++ head/sys/conf/files	Sat Jan 29 11:35:23 2011	(r218065)
@@ -568,6 +568,8 @@ dev/ath/if_ath.c		optional ath \
 	compile-with "${NORMAL_C} -I$S/dev/ath"
 dev/ath/if_ath_debug.c		optional ath \
 	compile-with "${NORMAL_C} -I$S/dev/ath"
+dev/ath/if_ath_tx.c		optional ath \
+	compile-with "${NORMAL_C} -I$S/dev/ath"
 dev/ath/if_ath_pci.c		optional ath pci \
 	compile-with "${NORMAL_C} -I$S/dev/ath"
 dev/ath/ah_osdep.c		optional ath \

Modified: head/sys/dev/ath/if_ath.c
==============================================================================
--- head/sys/dev/ath/if_ath.c	Sat Jan 29 10:32:00 2011	(r218064)
+++ head/sys/dev/ath/if_ath.c	Sat Jan 29 11:35:23 2011	(r218065)
@@ -90,6 +90,8 @@ __FBSDID("$FreeBSD$");
 #include <dev/ath/ath_hal/ah_diagcodes.h>
 
 #include <dev/ath/if_ath_debug.h>
+#include <dev/ath/if_ath_misc.h>
+#include <dev/ath/if_ath_tx.h>
 
 #ifdef ATH_TX99_DIAG
 #include <dev/ath/ath_tx99/ath_tx99.h>
@@ -111,15 +113,6 @@ __FBSDID("$FreeBSD$");
  */
 CTASSERT(ATH_BCBUF <= 8);
 
-/* unaligned little endian access */
-#define LE_READ_2(p)							\
-	((u_int16_t)							\
-	 ((((u_int8_t *)(p))[0]      ) | (((u_int8_t *)(p))[1] <<  8)))
-#define LE_READ_4(p)							\
-	((u_int32_t)							\
-	 ((((u_int8_t *)(p))[0]      ) | (((u_int8_t *)(p))[1] <<  8) |	\
-	  (((u_int8_t *)(p))[2] << 16) | (((u_int8_t *)(p))[3] << 24)))
-
 static struct ieee80211vap *ath_vap_create(struct ieee80211com *,
 		    const char name[IFNAMSIZ], int unit, int opmode,
 		    int flags, const uint8_t bssid[IEEE80211_ADDR_LEN],
@@ -184,9 +177,6 @@ static int	ath_tx_setup(struct ath_softc
 static int	ath_wme_update(struct ieee80211com *);
 static void	ath_tx_cleanupq(struct ath_softc *, struct ath_txq *);
 static void	ath_tx_cleanup(struct ath_softc *);
-static void	ath_freetx(struct mbuf *);
-static int	ath_tx_start(struct ath_softc *, struct ieee80211_node *,
-			     struct ath_buf *, struct mbuf *);
 static void	ath_tx_proc_q0(void *, int);
 static void	ath_tx_proc_q0123(void *, int);
 static void	ath_tx_proc(void *, int);
@@ -215,8 +205,6 @@ static int	ath_rate_setup(struct ath_sof
 static void	ath_setcurmode(struct ath_softc *, enum ieee80211_phymode);
 
 static void	ath_sysctlattach(struct ath_softc *);
-static int	ath_raw_xmit(struct ieee80211_node *,
-			struct mbuf *, const struct ieee80211_bpf_params *);
 static void	ath_announce(struct ath_softc *);
 static void	ath_sysctl_stats_attach(struct ath_softc *sc);
 
@@ -1670,7 +1658,7 @@ ath_reset_vap(struct ieee80211vap *vap, 
 	return ath_reset(ifp);
 }
 
-static struct ath_buf *
+struct ath_buf *
 _ath_getbuf_locked(struct ath_softc *sc)
 {
 	struct ath_buf *bf;
@@ -1690,7 +1678,7 @@ _ath_getbuf_locked(struct ath_softc *sc)
 	return bf;
 }
 
-static struct ath_buf *
+struct ath_buf *
 ath_getbuf(struct ath_softc *sc)
 {
 	struct ath_buf *bf;
@@ -1708,54 +1696,6 @@ ath_getbuf(struct ath_softc *sc)
 	return bf;
 }
 
-/*
- * Cleanup driver resources when we run out of buffers
- * while processing fragments; return the tx buffers
- * allocated and drop node references.
- */
-static void
-ath_txfrag_cleanup(struct ath_softc *sc,
-	ath_bufhead *frags, struct ieee80211_node *ni)
-{
-	struct ath_buf *bf, *next;
-
-	ATH_TXBUF_LOCK_ASSERT(sc);
-
-	STAILQ_FOREACH_SAFE(bf, frags, bf_list, next) {
-		/* NB: bf assumed clean */
-		STAILQ_REMOVE_HEAD(frags, bf_list);
-		STAILQ_INSERT_HEAD(&sc->sc_txbuf, bf, bf_list);
-		ieee80211_node_decref(ni);
-	}
-}
-
-/*
- * Setup xmit of a fragmented frame.  Allocate a buffer
- * for each frag and bump the node reference count to
- * reflect the held reference to be setup by ath_tx_start.
- */
-static int
-ath_txfrag_setup(struct ath_softc *sc, ath_bufhead *frags,
-	struct mbuf *m0, struct ieee80211_node *ni)
-{
-	struct mbuf *m;
-	struct ath_buf *bf;
-
-	ATH_TXBUF_LOCK(sc);
-	for (m = m0->m_nextpkt; m != NULL; m = m->m_nextpkt) {
-		bf = _ath_getbuf_locked(sc);
-		if (bf == NULL) {	/* out of buffers, cleanup */
-			ath_txfrag_cleanup(sc, frags, ni);
-			break;
-		}
-		ieee80211_node_incref(ni);
-		STAILQ_INSERT_TAIL(frags, bf, bf_list);
-	}
-	ATH_TXBUF_UNLOCK(sc);
-
-	return !STAILQ_EMPTY(frags);
-}
-
 static void
 ath_start(struct ifnet *ifp)
 {
@@ -4227,7 +4167,7 @@ ath_tx_cleanup(struct ath_softc *sc)
  * Return h/w rate index for an IEEE rate (w/o basic rate bit)
  * using the current rates in sc_rixmap.
  */
-static __inline int
+int
 ath_tx_findrix(const struct ath_softc *sc, uint8_t rate)
 {
 	int rix = sc->sc_rixmap[rate];
@@ -4236,623 +4176,6 @@ ath_tx_findrix(const struct ath_softc *s
 }
 
 /*
- * Reclaim mbuf resources.  For fragmented frames we
- * need to claim each frag chained with m_nextpkt.
- */
-static void
-ath_freetx(struct mbuf *m)
-{
-	struct mbuf *next;
-
-	do {
-		next = m->m_nextpkt;
-		m->m_nextpkt = NULL;
-		m_freem(m);
-	} while ((m = next) != NULL);
-}
-
-static int
-ath_tx_dmasetup(struct ath_softc *sc, struct ath_buf *bf, struct mbuf *m0)
-{
-	struct mbuf *m;
-	int error;
-
-	/*
-	 * Load the DMA map so any coalescing is done.  This
-	 * also calculates the number of descriptors we need.
-	 */
-	error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m0,
-				     bf->bf_segs, &bf->bf_nseg,
-				     BUS_DMA_NOWAIT);
-	if (error == EFBIG) {
-		/* XXX packet requires too many descriptors */
-		bf->bf_nseg = ATH_TXDESC+1;
-	} else if (error != 0) {
-		sc->sc_stats.ast_tx_busdma++;
-		ath_freetx(m0);
-		return error;
-	}
-	/*
-	 * Discard null packets and check for packets that
-	 * require too many TX descriptors.  We try to convert
-	 * the latter to a cluster.
-	 */
-	if (bf->bf_nseg > ATH_TXDESC) {		/* too many desc's, linearize */
-		sc->sc_stats.ast_tx_linear++;
-		m = m_collapse(m0, M_DONTWAIT, ATH_TXDESC);
-		if (m == NULL) {
-			ath_freetx(m0);
-			sc->sc_stats.ast_tx_nombuf++;
-			return ENOMEM;
-		}
-		m0 = m;
-		error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m0,
-					     bf->bf_segs, &bf->bf_nseg,
-					     BUS_DMA_NOWAIT);
-		if (error != 0) {
-			sc->sc_stats.ast_tx_busdma++;
-			ath_freetx(m0);
-			return error;
-		}
-		KASSERT(bf->bf_nseg <= ATH_TXDESC,
-		    ("too many segments after defrag; nseg %u", bf->bf_nseg));
-	} else if (bf->bf_nseg == 0) {		/* null packet, discard */
-		sc->sc_stats.ast_tx_nodata++;
-		ath_freetx(m0);
-		return EIO;
-	}
-	DPRINTF(sc, ATH_DEBUG_XMIT, "%s: m %p len %u\n",
-		__func__, m0, m0->m_pkthdr.len);
-	bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, BUS_DMASYNC_PREWRITE);
-	bf->bf_m = m0;
-
-	return 0;
-}
-
-static void
-ath_tx_handoff(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf)
-{
-	struct ath_hal *ah = sc->sc_ah;
-	struct ath_desc *ds, *ds0;
-	int i;
-
-	/*
-	 * Fillin the remainder of the descriptor info.
-	 */
-	ds0 = ds = bf->bf_desc;
-	for (i = 0; i < bf->bf_nseg; i++, ds++) {
-		ds->ds_data = bf->bf_segs[i].ds_addr;
-		if (i == bf->bf_nseg - 1)
-			ds->ds_link = 0;
-		else
-			ds->ds_link = bf->bf_daddr + sizeof(*ds) * (i + 1);
-		ath_hal_filltxdesc(ah, ds
-			, bf->bf_segs[i].ds_len	/* segment length */
-			, i == 0		/* first segment */
-			, i == bf->bf_nseg - 1	/* last segment */
-			, ds0			/* first descriptor */
-		);
-		DPRINTF(sc, ATH_DEBUG_XMIT,
-			"%s: %d: %08x %08x %08x %08x %08x %08x\n",
-			__func__, i, ds->ds_link, ds->ds_data,
-			ds->ds_ctl0, ds->ds_ctl1, ds->ds_hw[0], ds->ds_hw[1]);
-	}
-	/*
-	 * Insert the frame on the outbound list and pass it on
-	 * to the hardware.  Multicast frames buffered for power
-	 * save stations and transmit from the CAB queue are stored
-	 * on a s/w only queue and loaded on to the CAB queue in
-	 * the SWBA handler since frames only go out on DTIM and
-	 * to avoid possible races.
-	 */
-	ATH_TXQ_LOCK(txq);
-	KASSERT((bf->bf_flags & ATH_BUF_BUSY) == 0,
-	     ("busy status 0x%x", bf->bf_flags));
-	if (txq->axq_qnum != ATH_TXQ_SWQ) {
-#ifdef IEEE80211_SUPPORT_TDMA
-		int qbusy;
-
-		ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
-		qbusy = ath_hal_txqenabled(ah, txq->axq_qnum);
-		if (txq->axq_link == NULL) {
-			/*
-			 * Be careful writing the address to TXDP.  If
-			 * the tx q is enabled then this write will be
-			 * ignored.  Normally this is not an issue but
-			 * when tdma is in use and the q is beacon gated
-			 * this race can occur.  If the q is busy then
-			 * defer the work to later--either when another
-			 * packet comes along or when we prepare a beacon
-			 * frame at SWBA.
-			 */
-			if (!qbusy) {
-				ath_hal_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
-				txq->axq_flags &= ~ATH_TXQ_PUTPENDING;
-				DPRINTF(sc, ATH_DEBUG_XMIT,
-				    "%s: TXDP[%u] = %p (%p) depth %d\n",
-				    __func__, txq->axq_qnum,
-				    (caddr_t)bf->bf_daddr, bf->bf_desc,
-				    txq->axq_depth);
-			} else {
-				txq->axq_flags |= ATH_TXQ_PUTPENDING;
-				DPRINTF(sc, ATH_DEBUG_TDMA | ATH_DEBUG_XMIT,
-				    "%s: Q%u busy, defer enable\n", __func__,
-				    txq->axq_qnum);
-			}
-		} else {
-			*txq->axq_link = bf->bf_daddr;
-			DPRINTF(sc, ATH_DEBUG_XMIT,
-			    "%s: link[%u](%p)=%p (%p) depth %d\n", __func__,
-			    txq->axq_qnum, txq->axq_link,
-			    (caddr_t)bf->bf_daddr, bf->bf_desc, txq->axq_depth);
-			if ((txq->axq_flags & ATH_TXQ_PUTPENDING) && !qbusy) {
-				/*
-				 * The q was busy when we previously tried
-				 * to write the address of the first buffer
-				 * in the chain.  Since it's not busy now
-				 * handle this chore.  We are certain the
-				 * buffer at the front is the right one since
-				 * axq_link is NULL only when the buffer list
-				 * is/was empty.
-				 */
-				ath_hal_puttxbuf(ah, txq->axq_qnum,
-					STAILQ_FIRST(&txq->axq_q)->bf_daddr);
-				txq->axq_flags &= ~ATH_TXQ_PUTPENDING;
-				DPRINTF(sc, ATH_DEBUG_TDMA | ATH_DEBUG_XMIT,
-				    "%s: Q%u restarted\n", __func__,
-				    txq->axq_qnum);
-			}
-		}
-#else
-		ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
-		if (txq->axq_link == NULL) {
-			ath_hal_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
-			DPRINTF(sc, ATH_DEBUG_XMIT,
-			    "%s: TXDP[%u] = %p (%p) depth %d\n",
-			    __func__, txq->axq_qnum,
-			    (caddr_t)bf->bf_daddr, bf->bf_desc,
-			    txq->axq_depth);
-		} else {
-			*txq->axq_link = bf->bf_daddr;
-			DPRINTF(sc, ATH_DEBUG_XMIT,
-			    "%s: link[%u](%p)=%p (%p) depth %d\n", __func__,
-			    txq->axq_qnum, txq->axq_link,
-			    (caddr_t)bf->bf_daddr, bf->bf_desc, txq->axq_depth);
-		}
-#endif /* IEEE80211_SUPPORT_TDMA */
-		txq->axq_link = &bf->bf_desc[bf->bf_nseg - 1].ds_link;
-		ath_hal_txstart(ah, txq->axq_qnum);
-	} else {
-		if (txq->axq_link != NULL) {
-			struct ath_buf *last = ATH_TXQ_LAST(txq);
-			struct ieee80211_frame *wh;
-
-			/* mark previous frame */
-			wh = mtod(last->bf_m, struct ieee80211_frame *);
-			wh->i_fc[1] |= IEEE80211_FC1_MORE_DATA;
-			bus_dmamap_sync(sc->sc_dmat, last->bf_dmamap,
-			    BUS_DMASYNC_PREWRITE);
-
-			/* link descriptor */
-			*txq->axq_link = bf->bf_daddr;
-		}
-		ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
-		txq->axq_link = &bf->bf_desc[bf->bf_nseg - 1].ds_link;
-	}
-	ATH_TXQ_UNLOCK(txq);
-}
-
-static int
-ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf,
-    struct mbuf *m0)
-{
-	struct ieee80211vap *vap = ni->ni_vap;
-	struct ath_vap *avp = ATH_VAP(vap);
-	struct ath_hal *ah = sc->sc_ah;
-	struct ifnet *ifp = sc->sc_ifp;
-	struct ieee80211com *ic = ifp->if_l2com;
-	const struct chanAccParams *cap = &ic->ic_wme.wme_chanParams;
-	int error, iswep, ismcast, isfrag, ismrr;
-	int keyix, hdrlen, pktlen, try0;
-	u_int8_t rix, txrate, ctsrate;
-	u_int8_t cix = 0xff;		/* NB: silence compiler */
-	struct ath_desc *ds;
-	struct ath_txq *txq;
-	struct ieee80211_frame *wh;
-	u_int subtype, flags, ctsduration;
-	HAL_PKT_TYPE atype;
-	const HAL_RATE_TABLE *rt;
-	HAL_BOOL shortPreamble;
-	struct ath_node *an;
-	u_int pri;
-
-	wh = mtod(m0, struct ieee80211_frame *);
-	iswep = wh->i_fc[1] & IEEE80211_FC1_WEP;
-	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
-	isfrag = m0->m_flags & M_FRAG;
-	hdrlen = ieee80211_anyhdrsize(wh);
-	/*
-	 * Packet length must not include any
-	 * pad bytes; deduct them here.
-	 */
-	pktlen = m0->m_pkthdr.len - (hdrlen & 3);
-
-	if (iswep) {
-		const struct ieee80211_cipher *cip;
-		struct ieee80211_key *k;
-
-		/*
-		 * Construct the 802.11 header+trailer for an encrypted
-		 * frame. The only reason this can fail is because of an
-		 * unknown or unsupported cipher/key type.
-		 */
-		k = ieee80211_crypto_encap(ni, m0);
-		if (k == NULL) {
-			/*
-			 * This can happen when the key is yanked after the
-			 * frame was queued.  Just discard the frame; the
-			 * 802.11 layer counts failures and provides
-			 * debugging/diagnostics.
-			 */
-			ath_freetx(m0);
-			return EIO;
-		}
-		/*
-		 * Adjust the packet + header lengths for the crypto
-		 * additions and calculate the h/w key index.  When
-		 * a s/w mic is done the frame will have had any mic
-		 * added to it prior to entry so m0->m_pkthdr.len will
-		 * account for it. Otherwise we need to add it to the
-		 * packet length.
-		 */
-		cip = k->wk_cipher;
-		hdrlen += cip->ic_header;
-		pktlen += cip->ic_header + cip->ic_trailer;
-		/* NB: frags always have any TKIP MIC done in s/w */
-		if ((k->wk_flags & IEEE80211_KEY_SWMIC) == 0 && !isfrag)
-			pktlen += cip->ic_miclen;
-		keyix = k->wk_keyix;
-
-		/* packet header may have moved, reset our local pointer */
-		wh = mtod(m0, struct ieee80211_frame *);
-	} else if (ni->ni_ucastkey.wk_cipher == &ieee80211_cipher_none) {
-		/*
-		 * Use station key cache slot, if assigned.
-		 */
-		keyix = ni->ni_ucastkey.wk_keyix;
-		if (keyix == IEEE80211_KEYIX_NONE)
-			keyix = HAL_TXKEYIX_INVALID;
-	} else
-		keyix = HAL_TXKEYIX_INVALID;
-
-	pktlen += IEEE80211_CRC_LEN;
-
-	/*
-	 * Load the DMA map so any coalescing is done.  This
-	 * also calculates the number of descriptors we need.
-	 */
-	error = ath_tx_dmasetup(sc, bf, m0);
-	if (error != 0)
-		return error;
-	bf->bf_node = ni;			/* NB: held reference */
-	m0 = bf->bf_m;				/* NB: may have changed */
-	wh = mtod(m0, struct ieee80211_frame *);
-
-	/* setup descriptors */
-	ds = bf->bf_desc;
-	rt = sc->sc_currates;
-	KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
-
-	/*
-	 * NB: the 802.11 layer marks whether or not we should
-	 * use short preamble based on the current mode and
-	 * negotiated parameters.
-	 */
-	if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
-	    (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) {
-		shortPreamble = AH_TRUE;
-		sc->sc_stats.ast_tx_shortpre++;
-	} else {
-		shortPreamble = AH_FALSE;
-	}
-
-	an = ATH_NODE(ni);
-	flags = HAL_TXDESC_CLRDMASK;		/* XXX needed for crypto errs */
-	ismrr = 0;				/* default no multi-rate retry*/
-	pri = M_WME_GETAC(m0);			/* honor classification */
-	/* XXX use txparams instead of fixed values */
-	/*
-	 * Calculate Atheros packet type from IEEE80211 packet header,
-	 * setup for rate calculations, and select h/w transmit queue.
-	 */
-	switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
-	case IEEE80211_FC0_TYPE_MGT:
-		subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
-		if (subtype == IEEE80211_FC0_SUBTYPE_BEACON)
-			atype = HAL_PKT_TYPE_BEACON;
-		else if (subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP)
-			atype = HAL_PKT_TYPE_PROBE_RESP;
-		else if (subtype == IEEE80211_FC0_SUBTYPE_ATIM)
-			atype = HAL_PKT_TYPE_ATIM;
-		else
-			atype = HAL_PKT_TYPE_NORMAL;	/* XXX */
-		rix = an->an_mgmtrix;
-		txrate = rt->info[rix].rateCode;
-		if (shortPreamble)
-			txrate |= rt->info[rix].shortPreamble;
-		try0 = ATH_TXMGTTRY;
-		flags |= HAL_TXDESC_INTREQ;	/* force interrupt */
-		break;
-	case IEEE80211_FC0_TYPE_CTL:
-		atype = HAL_PKT_TYPE_PSPOLL;	/* stop setting of duration */
-		rix = an->an_mgmtrix;
-		txrate = rt->info[rix].rateCode;
-		if (shortPreamble)
-			txrate |= rt->info[rix].shortPreamble;
-		try0 = ATH_TXMGTTRY;
-		flags |= HAL_TXDESC_INTREQ;	/* force interrupt */
-		break;
-	case IEEE80211_FC0_TYPE_DATA:
-		atype = HAL_PKT_TYPE_NORMAL;		/* default */
-		/*
-		 * Data frames: multicast frames go out at a fixed rate,
-		 * EAPOL frames use the mgmt frame rate; otherwise consult
-		 * the rate control module for the rate to use.
-		 */
-		if (ismcast) {
-			rix = an->an_mcastrix;
-			txrate = rt->info[rix].rateCode;
-			if (shortPreamble)
-				txrate |= rt->info[rix].shortPreamble;
-			try0 = 1;
-		} else if (m0->m_flags & M_EAPOL) {
-			/* XXX? maybe always use long preamble? */
-			rix = an->an_mgmtrix;
-			txrate = rt->info[rix].rateCode;
-			if (shortPreamble)
-				txrate |= rt->info[rix].shortPreamble;
-			try0 = ATH_TXMAXTRY;	/* XXX?too many? */
-		} else {
-			ath_rate_findrate(sc, an, shortPreamble, pktlen,
-				&rix, &try0, &txrate);
-			sc->sc_txrix = rix;		/* for LED blinking */
-			sc->sc_lastdatarix = rix;	/* for fast frames */
-			if (try0 != ATH_TXMAXTRY)
-				ismrr = 1;
-		}
-		if (cap->cap_wmeParams[pri].wmep_noackPolicy)
-			flags |= HAL_TXDESC_NOACK;
-		break;
-	default:
-		if_printf(ifp, "bogus frame type 0x%x (%s)\n",
-			wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK, __func__);
-		/* XXX statistic */
-		ath_freetx(m0);
-		return EIO;
-	}
-	txq = sc->sc_ac2q[pri];
-
-	/*
-	 * When servicing one or more stations in power-save mode
-	 * (or) if there is some mcast data waiting on the mcast
-	 * queue (to prevent out of order delivery) multicast
-	 * frames must be buffered until after the beacon.
-	 */
-	if (ismcast && (vap->iv_ps_sta || avp->av_mcastq.axq_depth))
-		txq = &avp->av_mcastq;
-
-	/*
-	 * Calculate miscellaneous flags.
-	 */
-	if (ismcast) {
-		flags |= HAL_TXDESC_NOACK;	/* no ack on broad/multicast */
-	} else if (pktlen > vap->iv_rtsthreshold &&
-	    (ni->ni_ath_flags & IEEE80211_NODE_FF) == 0) {
-		flags |= HAL_TXDESC_RTSENA;	/* RTS based on frame length */
-		cix = rt->info[rix].controlRate;
-		sc->sc_stats.ast_tx_rts++;
-	}
-	if (flags & HAL_TXDESC_NOACK)		/* NB: avoid double counting */
-		sc->sc_stats.ast_tx_noack++;
-#ifdef IEEE80211_SUPPORT_TDMA
-	if (sc->sc_tdma && (flags & HAL_TXDESC_NOACK) == 0) {
-		DPRINTF(sc, ATH_DEBUG_TDMA,
-		    "%s: discard frame, ACK required w/ TDMA\n", __func__);
-		sc->sc_stats.ast_tdma_ack++;
-		ath_freetx(m0);
-		return EIO;
-	}
-#endif
-
-	/*
-	 * If 802.11g protection is enabled, determine whether
-	 * to use RTS/CTS or just CTS.  Note that this is only
-	 * done for OFDM unicast frames.
-	 */
-	if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
-	    rt->info[rix].phy == IEEE80211_T_OFDM &&
-	    (flags & HAL_TXDESC_NOACK) == 0) {
-		/* XXX fragments must use CCK rates w/ protection */
-		if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
-			flags |= HAL_TXDESC_RTSENA;
-		else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
-			flags |= HAL_TXDESC_CTSENA;
-		if (isfrag) {
-			/*
-			 * For frags it would be desirable to use the
-			 * highest CCK rate for RTS/CTS.  But stations
-			 * farther away may detect it at a lower CCK rate
-			 * so use the configured protection rate instead
-			 * (for now).
-			 */
-			cix = rt->info[sc->sc_protrix].controlRate;
-		} else
-			cix = rt->info[sc->sc_protrix].controlRate;
-		sc->sc_stats.ast_tx_protect++;
-	}
-
-	/*
-	 * Calculate duration.  This logically belongs in the 802.11
-	 * layer but it lacks sufficient information to calculate it.
-	 */
-	if ((flags & HAL_TXDESC_NOACK) == 0 &&
-	    (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL) {
-		u_int16_t dur;
-		if (shortPreamble)
-			dur = rt->info[rix].spAckDuration;
-		else
-			dur = rt->info[rix].lpAckDuration;
-		if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) {
-			dur += dur;		/* additional SIFS+ACK */
-			KASSERT(m0->m_nextpkt != NULL, ("no fragment"));
-			/*
-			 * Include the size of next fragment so NAV is
-			 * updated properly.  The last fragment uses only
-			 * the ACK duration
-			 */
-			dur += ath_hal_computetxtime(ah, rt,
-					m0->m_nextpkt->m_pkthdr.len,
-					rix, shortPreamble);
-		}
-		if (isfrag) {
-			/*
-			 * Force hardware to use computed duration for next
-			 * fragment by disabling multi-rate retry which updates
-			 * duration based on the multi-rate duration table.
-			 */
-			ismrr = 0;
-			try0 = ATH_TXMGTTRY;	/* XXX? */
-		}
-		*(u_int16_t *)wh->i_dur = htole16(dur);
-	}
-
-	/*
-	 * Calculate RTS/CTS rate and duration if needed.
-	 */
-	ctsduration = 0;
-	if (flags & (HAL_TXDESC_RTSENA|HAL_TXDESC_CTSENA)) {
-		/*
-		 * CTS transmit rate is derived from the transmit rate
-		 * by looking in the h/w rate table.  We must also factor
-		 * in whether or not a short preamble is to be used.
-		 */
-		/* NB: cix is set above where RTS/CTS is enabled */
-		KASSERT(cix != 0xff, ("cix not setup"));
-		ctsrate = rt->info[cix].rateCode;
-		/*
-		 * Compute the transmit duration based on the frame
-		 * size and the size of an ACK frame.  We call into the
-		 * HAL to do the computation since it depends on the
-		 * characteristics of the actual PHY being used.
-		 *
-		 * NB: CTS is assumed the same size as an ACK so we can
-		 *     use the precalculated ACK durations.
-		 */
-		if (shortPreamble) {
-			ctsrate |= rt->info[cix].shortPreamble;
-			if (flags & HAL_TXDESC_RTSENA)		/* SIFS + CTS */
-				ctsduration += rt->info[cix].spAckDuration;
-			ctsduration += ath_hal_computetxtime(ah,
-				rt, pktlen, rix, AH_TRUE);
-			if ((flags & HAL_TXDESC_NOACK) == 0)	/* SIFS + ACK */
-				ctsduration += rt->info[rix].spAckDuration;
-		} else {
-			if (flags & HAL_TXDESC_RTSENA)		/* SIFS + CTS */
-				ctsduration += rt->info[cix].lpAckDuration;
-			ctsduration += ath_hal_computetxtime(ah,
-				rt, pktlen, rix, AH_FALSE);
-			if ((flags & HAL_TXDESC_NOACK) == 0)	/* SIFS + ACK */
-				ctsduration += rt->info[rix].lpAckDuration;
-		}
-		/*
-		 * Must disable multi-rate retry when using RTS/CTS.
-		 */
-		ismrr = 0;
-		try0 = ATH_TXMGTTRY;		/* XXX */
-	} else
-		ctsrate = 0;
-
-	/*
-	 * At this point we are committed to sending the frame
-	 * and we don't need to look at m_nextpkt; clear it in
-	 * case this frame is part of frag chain.
-	 */
-	m0->m_nextpkt = NULL;
-
-	if (IFF_DUMPPKTS(sc, ATH_DEBUG_XMIT))
-		ieee80211_dump_pkt(ic, mtod(m0, const uint8_t *), m0->m_len,
-		    sc->sc_hwmap[rix].ieeerate, -1);
-
-	if (ieee80211_radiotap_active_vap(vap)) {
-		u_int64_t tsf = ath_hal_gettsf64(ah);
-
-		sc->sc_tx_th.wt_tsf = htole64(tsf);
-		sc->sc_tx_th.wt_flags = sc->sc_hwmap[rix].txflags;
-		if (iswep)
-			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
-		if (isfrag)
-			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_FRAG;
-		sc->sc_tx_th.wt_rate = sc->sc_hwmap[rix].ieeerate;
-		sc->sc_tx_th.wt_txpower = ni->ni_txpower;
-		sc->sc_tx_th.wt_antenna = sc->sc_txantenna;
-
-		ieee80211_radiotap_tx(vap, m0);
-	}
-
-	/*
-	 * Determine if a tx interrupt should be generated for
-	 * this descriptor.  We take a tx interrupt to reap
-	 * descriptors when the h/w hits an EOL condition or
-	 * when the descriptor is specifically marked to generate
-	 * an interrupt.  We periodically mark descriptors in this
-	 * way to insure timely replenishing of the supply needed
-	 * for sending frames.  Defering interrupts reduces system
-	 * load and potentially allows more concurrent work to be
-	 * done but if done to aggressively can cause senders to
-	 * backup.
-	 *
-	 * NB: use >= to deal with sc_txintrperiod changing
-	 *     dynamically through sysctl.
-	 */
-	if (flags & HAL_TXDESC_INTREQ) {
-		txq->axq_intrcnt = 0;
-	} else if (++txq->axq_intrcnt >= sc->sc_txintrperiod) {
-		flags |= HAL_TXDESC_INTREQ;
-		txq->axq_intrcnt = 0;
-	}
-
-	/*
-	 * Formulate first tx descriptor with tx controls.
-	 */
-	/* XXX check return value? */
-	ath_hal_setuptxdesc(ah, ds
-		, pktlen		/* packet length */
-		, hdrlen		/* header length */
-		, atype			/* Atheros packet type */
-		, ni->ni_txpower	/* txpower */
-		, txrate, try0		/* series 0 rate/tries */
-		, keyix			/* key cache index */
-		, sc->sc_txantenna	/* antenna mode */
-		, flags			/* flags */
-		, ctsrate		/* rts/cts rate */
-		, ctsduration		/* rts/cts duration */
-	);
-	bf->bf_txflags = flags;
-	/*
-	 * Setup the multi-rate retry state only when we're
-	 * going to use it.  This assumes ath_hal_setuptxdesc
-	 * initializes the descriptors (so we don't have to)
-	 * when the hardware supports multi-rate retry and
-	 * we don't use it.
-	 */
-	if (ismrr)
-		ath_rate_setupxtxdesc(sc, an, ds, shortPreamble, rix);
-
-	ath_tx_handoff(sc, txq, bf);
-	return 0;
-}
-
-/*
  * Process completed xmit descriptors from the specified queue.
  */
 static int
@@ -6586,276 +5909,6 @@ ath_sysctlattach(struct ath_softc *sc)
 #endif
 }
 
-static int
-ath_tx_raw_start(struct ath_softc *sc, struct ieee80211_node *ni,
-	struct ath_buf *bf, struct mbuf *m0,
-	const struct ieee80211_bpf_params *params)
-{
-	struct ifnet *ifp = sc->sc_ifp;
-	struct ieee80211com *ic = ifp->if_l2com;
-	struct ath_hal *ah = sc->sc_ah;
-	struct ieee80211vap *vap = ni->ni_vap;
-	int error, ismcast, ismrr;
-	int keyix, hdrlen, pktlen, try0, txantenna;
-	u_int8_t rix, cix, txrate, ctsrate, rate1, rate2, rate3;
-	struct ieee80211_frame *wh;
-	u_int flags, ctsduration;
-	HAL_PKT_TYPE atype;
-	const HAL_RATE_TABLE *rt;
-	struct ath_desc *ds;
-	u_int pri;
-
-	wh = mtod(m0, struct ieee80211_frame *);
-	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
-	hdrlen = ieee80211_anyhdrsize(wh);
-	/*
-	 * Packet length must not include any
-	 * pad bytes; deduct them here.
-	 */
-	/* XXX honor IEEE80211_BPF_DATAPAD */
-	pktlen = m0->m_pkthdr.len - (hdrlen & 3) + IEEE80211_CRC_LEN;
-
-	if (params->ibp_flags & IEEE80211_BPF_CRYPTO) {
-		const struct ieee80211_cipher *cip;
-		struct ieee80211_key *k;
-
-		/*
-		 * Construct the 802.11 header+trailer for an encrypted
-		 * frame. The only reason this can fail is because of an
-		 * unknown or unsupported cipher/key type.
-		 */
-		k = ieee80211_crypto_encap(ni, m0);
-		if (k == NULL) {
-			/*
-			 * This can happen when the key is yanked after the
-			 * frame was queued.  Just discard the frame; the
-			 * 802.11 layer counts failures and provides
-			 * debugging/diagnostics.
-			 */
-			ath_freetx(m0);
-			return EIO;
-		}
-		/*
-		 * Adjust the packet + header lengths for the crypto
-		 * additions and calculate the h/w key index.  When
-		 * a s/w mic is done the frame will have had any mic
-		 * added to it prior to entry so m0->m_pkthdr.len will
-		 * account for it. Otherwise we need to add it to the
-		 * packet length.
-		 */
-		cip = k->wk_cipher;
-		hdrlen += cip->ic_header;
-		pktlen += cip->ic_header + cip->ic_trailer;
-		/* NB: frags always have any TKIP MIC done in s/w */
-		if ((k->wk_flags & IEEE80211_KEY_SWMIC) == 0)
-			pktlen += cip->ic_miclen;
-		keyix = k->wk_keyix;
-
-		/* packet header may have moved, reset our local pointer */
-		wh = mtod(m0, struct ieee80211_frame *);
-	} else if (ni->ni_ucastkey.wk_cipher == &ieee80211_cipher_none) {
-		/*
-		 * Use station key cache slot, if assigned.
-		 */
-		keyix = ni->ni_ucastkey.wk_keyix;
-		if (keyix == IEEE80211_KEYIX_NONE)
-			keyix = HAL_TXKEYIX_INVALID;
-	} else
-		keyix = HAL_TXKEYIX_INVALID;
-
-	error = ath_tx_dmasetup(sc, bf, m0);
-	if (error != 0)
-		return error;
-	m0 = bf->bf_m;				/* NB: may have changed */
-	wh = mtod(m0, struct ieee80211_frame *);
-	bf->bf_node = ni;			/* NB: held reference */
-
-	flags = HAL_TXDESC_CLRDMASK;		/* XXX needed for crypto errs */
-	flags |= HAL_TXDESC_INTREQ;		/* force interrupt */
-	if (params->ibp_flags & IEEE80211_BPF_RTS)
-		flags |= HAL_TXDESC_RTSENA;
-	else if (params->ibp_flags & IEEE80211_BPF_CTS)
-		flags |= HAL_TXDESC_CTSENA;
-	/* XXX leave ismcast to injector? */
-	if ((params->ibp_flags & IEEE80211_BPF_NOACK) || ismcast)
-		flags |= HAL_TXDESC_NOACK;
-
-	rt = sc->sc_currates;
-	KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
-	rix = ath_tx_findrix(sc, params->ibp_rate0);
-	txrate = rt->info[rix].rateCode;
-	if (params->ibp_flags & IEEE80211_BPF_SHORTPRE)
-		txrate |= rt->info[rix].shortPreamble;
-	sc->sc_txrix = rix;
-	try0 = params->ibp_try0;
-	ismrr = (params->ibp_try1 != 0);
-	txantenna = params->ibp_pri >> 2;
-	if (txantenna == 0)			/* XXX? */
-		txantenna = sc->sc_txantenna;
-	ctsduration = 0;
-	if (flags & (HAL_TXDESC_CTSENA | HAL_TXDESC_RTSENA)) {
-		cix = ath_tx_findrix(sc, params->ibp_ctsrate);
-		ctsrate = rt->info[cix].rateCode;
-		if (params->ibp_flags & IEEE80211_BPF_SHORTPRE) {
-			ctsrate |= rt->info[cix].shortPreamble;
-			if (flags & HAL_TXDESC_RTSENA)		/* SIFS + CTS */
-				ctsduration += rt->info[cix].spAckDuration;
-			ctsduration += ath_hal_computetxtime(ah,
-				rt, pktlen, rix, AH_TRUE);
-			if ((flags & HAL_TXDESC_NOACK) == 0)	/* SIFS + ACK */
-				ctsduration += rt->info[rix].spAckDuration;
-		} else {
-			if (flags & HAL_TXDESC_RTSENA)		/* SIFS + CTS */
-				ctsduration += rt->info[cix].lpAckDuration;
-			ctsduration += ath_hal_computetxtime(ah,
-				rt, pktlen, rix, AH_FALSE);
-			if ((flags & HAL_TXDESC_NOACK) == 0)	/* SIFS + ACK */
-				ctsduration += rt->info[rix].lpAckDuration;
-		}
-		ismrr = 0;			/* XXX */
-	} else
-		ctsrate = 0;
-	pri = params->ibp_pri & 3;
-	/*
-	 * NB: we mark all packets as type PSPOLL so the h/w won't
-	 * set the sequence number, duration, etc.
-	 */
-	atype = HAL_PKT_TYPE_PSPOLL;
-
-	if (IFF_DUMPPKTS(sc, ATH_DEBUG_XMIT))
-		ieee80211_dump_pkt(ic, mtod(m0, caddr_t), m0->m_len,
-		    sc->sc_hwmap[rix].ieeerate, -1);
-
-	if (ieee80211_radiotap_active_vap(vap)) {
-		u_int64_t tsf = ath_hal_gettsf64(ah);
-
-		sc->sc_tx_th.wt_tsf = htole64(tsf);
-		sc->sc_tx_th.wt_flags = sc->sc_hwmap[rix].txflags;
-		if (wh->i_fc[1] & IEEE80211_FC1_WEP)
-			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
-		if (m0->m_flags & M_FRAG)
-			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_FRAG;
-		sc->sc_tx_th.wt_rate = sc->sc_hwmap[rix].ieeerate;
-		sc->sc_tx_th.wt_txpower = ni->ni_txpower;
-		sc->sc_tx_th.wt_antenna = sc->sc_txantenna;
-
-		ieee80211_radiotap_tx(vap, m0);
-	}
-
-	/*
-	 * Formulate first tx descriptor with tx controls.
-	 */
-	ds = bf->bf_desc;
-	/* XXX check return value? */
-	ath_hal_setuptxdesc(ah, ds
-		, pktlen		/* packet length */
-		, hdrlen		/* header length */
-		, atype			/* Atheros packet type */
-		, params->ibp_power	/* txpower */
-		, txrate, try0		/* series 0 rate/tries */
-		, keyix			/* key cache index */
-		, txantenna		/* antenna mode */
-		, flags			/* flags */
-		, ctsrate		/* rts/cts rate */
-		, ctsduration		/* rts/cts duration */
-	);
-	bf->bf_txflags = flags;
-
-	if (ismrr) {
-		rix = ath_tx_findrix(sc, params->ibp_rate1);
-		rate1 = rt->info[rix].rateCode;
-		if (params->ibp_flags & IEEE80211_BPF_SHORTPRE)
-			rate1 |= rt->info[rix].shortPreamble;
-		if (params->ibp_try2) {
-			rix = ath_tx_findrix(sc, params->ibp_rate2);
-			rate2 = rt->info[rix].rateCode;
-			if (params->ibp_flags & IEEE80211_BPF_SHORTPRE)
-				rate2 |= rt->info[rix].shortPreamble;
-		} else
-			rate2 = 0;
-		if (params->ibp_try3) {
-			rix = ath_tx_findrix(sc, params->ibp_rate3);
-			rate3 = rt->info[rix].rateCode;
-			if (params->ibp_flags & IEEE80211_BPF_SHORTPRE)
-				rate3 |= rt->info[rix].shortPreamble;
-		} else
-			rate3 = 0;
-		ath_hal_setupxtxdesc(ah, ds
-			, rate1, params->ibp_try1	/* series 1 */
-			, rate2, params->ibp_try2	/* series 2 */
-			, rate3, params->ibp_try3	/* series 3 */
-		);
-	}
-
-	/* NB: no buffered multicast in power save support */
-	ath_tx_handoff(sc, sc->sc_ac2q[pri], bf);
-	return 0;
-}
-
-static int
-ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
-	const struct ieee80211_bpf_params *params)
-{
-	struct ieee80211com *ic = ni->ni_ic;
-	struct ifnet *ifp = ic->ic_ifp;
-	struct ath_softc *sc = ifp->if_softc;
-	struct ath_buf *bf;
-	int error;
-
-	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid) {
-		DPRINTF(sc, ATH_DEBUG_XMIT, "%s: discard frame, %s", __func__,
-		    (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ?
-			"!running" : "invalid");
-		m_freem(m);
-		error = ENETDOWN;
-		goto bad;
-	}
-	/*
-	 * Grab a TX buffer and associated resources.
-	 */
-	bf = ath_getbuf(sc);
-	if (bf == NULL) {
-		sc->sc_stats.ast_tx_nobuf++;
-		m_freem(m);
-		error = ENOBUFS;
-		goto bad;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



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