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 ***
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to