Author: adrian
Date: Tue Nov  8 17:08:12 2011
New Revision: 227344
URL: http://svn.freebsd.org/changeset/base/227344

Log:
  Migrate the STAILQ lists to TAILQs.
  
  A bunch of the 11n TX aggregation logic wants to traverse lists of buffers
  in various ways. In order to provide O(1) behaviour in this instance,
  use TAILQs.
  
  This does blow out the memory footprint and CPU cycles slightly for some
  of these operations. I may convert some of these back to STAILQs once
  the rest of the software transmit queue handling has been stabilised.
  
  Sponsored by: Hobnob, Inc.

Modified:
  head/sys/dev/ath/if_ath.c
  head/sys/dev/ath/if_ath_sysctl.c
  head/sys/dev/ath/if_ath_tx.c
  head/sys/dev/ath/if_athvar.h

Modified: head/sys/dev/ath/if_ath.c
==============================================================================
--- head/sys/dev/ath/if_ath.c   Tue Nov  8 15:38:21 2011        (r227343)
+++ head/sys/dev/ath/if_ath.c   Tue Nov  8 17:08:12 2011        (r227344)
@@ -263,7 +263,7 @@ static      int ath_bstuck_threshold = 4;           /*
 SYSCTL_INT(_hw_ath, OID_AUTO, bstuck, CTLFLAG_RW, &ath_bstuck_threshold,
            0, "max missed beacon xmits before chip reset");
 
-static MALLOC_DEFINE(M_ATHDEV, "athdev", "ath driver dma buffers");
+MALLOC_DEFINE(M_ATHDEV, "athdev", "ath driver dma buffers");
 
 #define        HAL_MODE_HT20 (HAL_MODE_11NG_HT20 | HAL_MODE_11NA_HT20)
 #define        HAL_MODE_HT40 \
@@ -952,7 +952,7 @@ ath_vap_create(struct ieee80211com *ic,
        /*
         * Check that a beacon buffer is available; the code below assumes it.
         */
-       if (needbeacon & STAILQ_EMPTY(&sc->sc_bbuf)) {
+       if (needbeacon & TAILQ_EMPTY(&sc->sc_bbuf)) {
                device_printf(sc->sc_dev, "no beacon buffer available\n");
                goto bad;
        }
@@ -1014,8 +1014,8 @@ ath_vap_create(struct ieee80211com *ic,
                 * multicast frames.  We know a beacon buffer is
                 * available because we checked above.
                 */
-               avp->av_bcbuf = STAILQ_FIRST(&sc->sc_bbuf);
-               STAILQ_REMOVE_HEAD(&sc->sc_bbuf, bf_list);
+               avp->av_bcbuf = TAILQ_FIRST(&sc->sc_bbuf);
+               TAILQ_REMOVE(&sc->sc_bbuf, avp->av_bcbuf, bf_list);
                if (opmode != IEEE80211_M_IBSS || !sc->sc_hasveol) {
                        /*
                         * Assign the vap to a beacon xmit slot.  As above
@@ -1796,14 +1796,14 @@ _ath_getbuf_locked(struct ath_softc *sc)
 
        ATH_TXBUF_LOCK_ASSERT(sc);
 
-       bf = STAILQ_FIRST(&sc->sc_txbuf);
+       bf = TAILQ_FIRST(&sc->sc_txbuf);
        if (bf != NULL && (bf->bf_flags & ATH_BUF_BUSY) == 0)
-               STAILQ_REMOVE_HEAD(&sc->sc_txbuf, bf_list);
+               TAILQ_REMOVE(&sc->sc_txbuf, bf, bf_list);
        else
                bf = NULL;
        if (bf == NULL) {
                DPRINTF(sc, ATH_DEBUG_XMIT, "%s: %s\n", __func__,
-                   STAILQ_FIRST(&sc->sc_txbuf) == NULL ?
+                   TAILQ_FIRST(&sc->sc_txbuf) == NULL ?
                        "out of xmit buffers" : "xmit buffer busy");
        }
        return bf;
@@ -1849,7 +1849,7 @@ ath_start(struct ifnet *ifp)
                IFQ_DEQUEUE(&ifp->if_snd, m);
                if (m == NULL) {
                        ATH_TXBUF_LOCK(sc);
-                       STAILQ_INSERT_HEAD(&sc->sc_txbuf, bf, bf_list);
+                       TAILQ_INSERT_HEAD(&sc->sc_txbuf, bf, bf_list);
                        ATH_TXBUF_UNLOCK(sc);
                        break;
                }
@@ -1860,7 +1860,7 @@ ath_start(struct ifnet *ifp)
                 * buffers to send all the fragments so all
                 * go out or none...
                 */
-               STAILQ_INIT(&frags);
+               TAILQ_INIT(&frags);
                if ((m->m_flags & M_FRAG) &&
                    !ath_txfrag_setup(sc, &frags, m, ni)) {
                        DPRINTF(sc, ATH_DEBUG_XMIT,
@@ -1892,7 +1892,7 @@ ath_start(struct ifnet *ifp)
                        bf->bf_m = NULL;
                        bf->bf_node = NULL;
                        ATH_TXBUF_LOCK(sc);
-                       STAILQ_INSERT_HEAD(&sc->sc_txbuf, bf, bf_list);
+                       TAILQ_INSERT_HEAD(&sc->sc_txbuf, bf, bf_list);
                        ath_txfrag_cleanup(sc, &frags, ni);
                        ATH_TXBUF_UNLOCK(sc);
                        if (ni != NULL)
@@ -1913,9 +1913,9 @@ ath_start(struct ifnet *ifp)
                                goto reclaim;
                        }
                        m = next;
-                       bf = STAILQ_FIRST(&frags);
+                       bf = TAILQ_FIRST(&frags);
                        KASSERT(bf != NULL, ("no buf for txfrag"));
-                       STAILQ_REMOVE_HEAD(&frags, bf_list);
+                       TAILQ_REMOVE(&frags, bf, bf_list);
                        goto nextfrag;
                }
 
@@ -2414,7 +2414,7 @@ ath_beacon_update(struct ieee80211vap *v
 static void
 ath_txqmove(struct ath_txq *dst, struct ath_txq *src)
 {
-       STAILQ_CONCAT(&dst->axq_q, &src->axq_q);
+       TAILQ_CONCAT(&dst->axq_q, &src->axq_q, bf_list);
        dst->axq_link = src->axq_link;
        src->axq_link = NULL;
        dst->axq_depth += src->axq_depth;
@@ -2609,7 +2609,7 @@ ath_beacon_generate(struct ath_softc *sc
                         * Move frames from the s/w mcast q to the h/w cab q.
                         * XXX MORE_DATA bit
                         */
-                       bfm = STAILQ_FIRST(&avp->av_mcastq.axq_q);
+                       bfm = TAILQ_FIRST(&avp->av_mcastq.axq_q);
                        if (cabq->axq_link != NULL) {
                                *cabq->axq_link = bfm->bf_daddr;
                        } else
@@ -2620,7 +2620,7 @@ ath_beacon_generate(struct ath_softc *sc
                        sc->sc_stats.ast_cabq_xmit += nmcastq;
                }
                /* NB: gated by beacon so safe to start here */
-               if (! STAILQ_EMPTY(&(cabq->axq_q)))
+               if (! TAILQ_EMPTY(&(cabq->axq_q)))
                        ath_hal_txstart(ah, cabq->axq_qnum);
                ATH_TXQ_UNLOCK(&avp->av_mcastq);
                ATH_TXQ_UNLOCK(cabq);
@@ -2699,7 +2699,7 @@ ath_beacon_return(struct ath_softc *sc, 
                ieee80211_free_node(bf->bf_node);
                bf->bf_node = NULL;
        }
-       STAILQ_INSERT_TAIL(&sc->sc_bbuf, bf, bf_list);
+       TAILQ_INSERT_TAIL(&sc->sc_bbuf, bf, bf_list);
 }
 
 /*
@@ -2710,7 +2710,7 @@ ath_beacon_free(struct ath_softc *sc)
 {
        struct ath_buf *bf;
 
-       STAILQ_FOREACH(bf, &sc->sc_bbuf, bf_list) {
+       TAILQ_FOREACH(bf, &sc->sc_bbuf, bf_list) {
                if (bf->bf_m != NULL) {
                        bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
                        m_freem(bf->bf_m);
@@ -3029,7 +3029,7 @@ ath_descdma_setup(struct ath_softc *sc,
        }
        dd->dd_bufptr = bf;
 
-       STAILQ_INIT(head);
+       TAILQ_INIT(head);
        for (i = 0; i < nbuf; i++, bf++, ds += (ndesc * desc_len)) {
                bf->bf_desc = (struct ath_desc *) ds;
                bf->bf_daddr = DS2PHYS(dd, ds);
@@ -3055,7 +3055,7 @@ ath_descdma_setup(struct ath_softc *sc,
                        ath_descdma_cleanup(sc, dd, head);
                        return error;
                }
-               STAILQ_INSERT_TAIL(head, bf, bf_list);
+               TAILQ_INSERT_TAIL(head, bf, bf_list);
        }
        return 0;
 fail3:
@@ -3084,7 +3084,7 @@ ath_descdma_cleanup(struct ath_softc *sc
        bus_dmamap_destroy(dd->dd_dmat, dd->dd_dmamap);
        bus_dma_tag_destroy(dd->dd_dmat);
 
-       STAILQ_FOREACH(bf, head, bf_list) {
+       TAILQ_FOREACH(bf, head, bf_list) {
                if (bf->bf_m) {
                        m_freem(bf->bf_m);
                        bf->bf_m = NULL;
@@ -3103,7 +3103,7 @@ ath_descdma_cleanup(struct ath_softc *sc
                }
        }
 
-       STAILQ_INIT(head);
+       TAILQ_INIT(head);
        free(dd->dd_bufptr, M_ATHDEV);
        memset(dd, 0, sizeof(*dd));
 }
@@ -3485,7 +3485,7 @@ ath_rx_proc(void *arg, int npending)
        sc->sc_stats.ast_rx_noise = nf;
        tsf = ath_hal_gettsf64(ah);
        do {
-               bf = STAILQ_FIRST(&sc->sc_rxbuf);
+               bf = TAILQ_FIRST(&sc->sc_rxbuf);
                if (sc->sc_rxslink && bf == NULL) {     /* NB: shouldn't happen 
*/
                        if_printf(ifp, "%s: no buffer!\n", __func__);
                        break;
@@ -3505,7 +3505,7 @@ ath_rx_proc(void *arg, int npending)
                         */
                        /* XXX make debug msg */
                        if_printf(ifp, "%s: no mbuf!\n", __func__);
-                       STAILQ_REMOVE_HEAD(&sc->sc_rxbuf, bf_list);
+                       TAILQ_REMOVE(&sc->sc_rxbuf, bf, bf_list);
                        goto rx_next;
                }
                ds = bf->bf_desc;
@@ -3535,7 +3535,8 @@ ath_rx_proc(void *arg, int npending)
 #endif
                if (status == HAL_EINPROGRESS)
                        break;
-               STAILQ_REMOVE_HEAD(&sc->sc_rxbuf, bf_list);
+
+               TAILQ_REMOVE(&sc->sc_rxbuf, bf, bf_list);
 
                /* These aren't specifically errors */
                if (rs->rs_flags & HAL_RX_GI)
@@ -3804,7 +3805,7 @@ rx_accept:
                                ath_led_event(sc, 0);
                }
 rx_next:
-               STAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list);
+               TAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list);
        } while (ath_rxbuf_init(sc, bf) == 0);
 
        /* rx signal state monitoring */
@@ -3853,7 +3854,9 @@ ath_txq_init(struct ath_softc *sc, struc
        txq->axq_depth = 0;
        txq->axq_intrcnt = 0;
        txq->axq_link = NULL;
-       STAILQ_INIT(&txq->axq_q);
+       txq->axq_softc = sc;
+       TAILQ_INIT(&txq->axq_q);
+       TAILQ_INIT(&txq->axq_tidq);
        ATH_TXQ_LOCK_INIT(sc, txq);
 }
 
@@ -4088,7 +4091,7 @@ ath_tx_processq(struct ath_softc *sc, st
        for (;;) {
                ATH_TXQ_LOCK(txq);
                txq->axq_intrcnt = 0;   /* reset periodic desc intr count */
-               bf = STAILQ_FIRST(&txq->axq_q);
+               bf = TAILQ_FIRST(&txq->axq_q);
                if (bf == NULL) {
                        ATH_TXQ_UNLOCK(txq);
                        break;
@@ -4106,7 +4109,7 @@ ath_tx_processq(struct ath_softc *sc, st
                        ATH_TXQ_UNLOCK(txq);
                        break;
                }
-               ATH_TXQ_REMOVE_HEAD(txq, bf_list);
+               ATH_TXQ_REMOVE(txq, bf, bf_list);
 #ifdef IEEE80211_SUPPORT_TDMA
                if (txq->axq_depth > 0) {
                        /*
@@ -4199,10 +4202,10 @@ ath_tx_processq(struct ath_softc *sc, st
                bf->bf_node = NULL;
 
                ATH_TXBUF_LOCK(sc);
-               last = STAILQ_LAST(&sc->sc_txbuf, ath_buf, bf_list);
+               last = TAILQ_LAST(&sc->sc_txbuf, ath_bufhead_s);
                if (last != NULL)
                        last->bf_flags &= ~ATH_BUF_BUSY;
-               STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
+               TAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
                ATH_TXBUF_UNLOCK(sc);
        }
 #ifdef IEEE80211_SUPPORT_SUPERG
@@ -4327,19 +4330,19 @@ ath_tx_draintxq(struct ath_softc *sc, st
         *     we do not need to block ath_tx_proc
         */
        ATH_TXBUF_LOCK(sc);
-       bf = STAILQ_LAST(&sc->sc_txbuf, ath_buf, bf_list);
+       bf = TAILQ_LAST(&sc->sc_txbuf, ath_bufhead_s);
        if (bf != NULL)
                bf->bf_flags &= ~ATH_BUF_BUSY;
        ATH_TXBUF_UNLOCK(sc);
        for (ix = 0;; ix++) {
                ATH_TXQ_LOCK(txq);
-               bf = STAILQ_FIRST(&txq->axq_q);
+               bf = TAILQ_FIRST(&txq->axq_q);
                if (bf == NULL) {
                        txq->axq_link = NULL;
                        ATH_TXQ_UNLOCK(txq);
                        break;
                }
-               ATH_TXQ_REMOVE_HEAD(txq, bf_list);
+               ATH_TXQ_REMOVE(txq, bf, bf_list);
                ATH_TXQ_UNLOCK(txq);
 #ifdef ATH_DEBUG
                if (sc->sc_debug & ATH_DEBUG_RESET) {
@@ -4368,7 +4371,7 @@ ath_tx_draintxq(struct ath_softc *sc, st
                bf->bf_flags &= ~ATH_BUF_BUSY;
 
                ATH_TXBUF_LOCK(sc);
-               STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
+               TAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
                ATH_TXBUF_UNLOCK(sc);
        }
 }
@@ -4412,7 +4415,7 @@ ath_draintxq(struct ath_softc *sc)
                        ath_tx_draintxq(sc, &sc->sc_txq[i]);
 #ifdef ATH_DEBUG
        if (sc->sc_debug & ATH_DEBUG_RESET) {
-               struct ath_buf *bf = STAILQ_FIRST(&sc->sc_bbuf);
+               struct ath_buf *bf = TAILQ_FIRST(&sc->sc_bbuf);
                if (bf != NULL && bf->bf_m != NULL) {
                        ath_printtxbuf(sc, bf, sc->sc_bhalq, 0,
                                ath_hal_txprocdesc(ah, bf->bf_desc,
@@ -4450,7 +4453,7 @@ ath_stoprecv(struct ath_softc *sc)
                printf("%s: rx queue %p, link %p\n", __func__,
                        (caddr_t)(uintptr_t) ath_hal_getrxbuf(ah), 
sc->sc_rxlink);
                ix = 0;
-               STAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list) {
+               TAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list) {
                        struct ath_desc *ds = bf->bf_desc;
                        struct ath_rx_status *rs = &bf->bf_status.ds_rxstat;
                        HAL_STATUS status = ath_hal_rxprocdesc(ah, ds,
@@ -4480,7 +4483,7 @@ ath_startrecv(struct ath_softc *sc)
 
        sc->sc_rxlink = NULL;
        sc->sc_rxpending = NULL;
-       STAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list) {
+       TAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list) {
                int error = ath_rxbuf_init(sc, bf);
                if (error != 0) {
                        DPRINTF(sc, ATH_DEBUG_RECV,
@@ -4490,7 +4493,7 @@ ath_startrecv(struct ath_softc *sc)
                }
        }
 
-       bf = STAILQ_FIRST(&sc->sc_rxbuf);
+       bf = TAILQ_FIRST(&sc->sc_rxbuf);
        ath_hal_putrxbuf(ah, bf->bf_daddr);
        ath_hal_rxena(ah);              /* enable recv descriptors */
        ath_mode_init(sc);              /* set filters, etc. */

Modified: head/sys/dev/ath/if_ath_sysctl.c
==============================================================================
--- head/sys/dev/ath/if_ath_sysctl.c    Tue Nov  8 15:38:21 2011        
(r227343)
+++ head/sys/dev/ath/if_ath_sysctl.c    Tue Nov  8 17:08:12 2011        
(r227344)
@@ -346,7 +346,7 @@ ath_sysctl_txagg(SYSCTL_HANDLER_ARGS)
 
        i = t = 0;
        ATH_TXBUF_LOCK(sc);
-       STAILQ_FOREACH(bf, &sc->sc_txbuf, bf_list) {
+       TAILQ_FOREACH(bf, &sc->sc_txbuf, bf_list) {
                if (bf->bf_flags & ATH_BUF_BUSY) {
                        printf("Busy: %d\n", t);
                        i++;

Modified: head/sys/dev/ath/if_ath_tx.c
==============================================================================
--- head/sys/dev/ath/if_ath_tx.c        Tue Nov  8 15:38:21 2011        
(r227343)
+++ head/sys/dev/ath/if_ath_tx.c        Tue Nov  8 17:08:12 2011        
(r227344)
@@ -116,10 +116,10 @@ ath_txfrag_cleanup(struct ath_softc *sc,
 
        ATH_TXBUF_LOCK_ASSERT(sc);
 
-       STAILQ_FOREACH_SAFE(bf, frags, bf_list, next) {
+       TAILQ_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);
+               TAILQ_REMOVE(frags, bf, bf_list);
+               TAILQ_INSERT_HEAD(&sc->sc_txbuf, bf, bf_list);
                ieee80211_node_decref(ni);
        }
 }
@@ -144,11 +144,11 @@ ath_txfrag_setup(struct ath_softc *sc, a
                        break;
                }
                ieee80211_node_incref(ni);
-               STAILQ_INSERT_TAIL(frags, bf, bf_list);
+               TAILQ_INSERT_TAIL(frags, bf, bf_list);
        }
        ATH_TXBUF_UNLOCK(sc);
 
-       return !STAILQ_EMPTY(frags);
+       return !TAILQ_EMPTY(frags);
 }
 
 /*
@@ -323,7 +323,7 @@ ath_tx_handoff(struct ath_softc *sc, str
                                 * is/was empty.
                                 */
                                ath_hal_puttxbuf(ah, txq->axq_qnum,
-                                       STAILQ_FIRST(&txq->axq_q)->bf_daddr);
+                                       TAILQ_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__,
@@ -351,7 +351,7 @@ ath_tx_handoff(struct ath_softc *sc, str
                ath_hal_txstart(ah, txq->axq_qnum);
        } else {
                if (txq->axq_link != NULL) {
-                       struct ath_buf *last = ATH_TXQ_LAST(txq);
+                       struct ath_buf *last = ATH_TXQ_LAST(txq, axq_q_s);
                        struct ieee80211_frame *wh;
 
                        /* mark previous frame */
@@ -1114,7 +1114,7 @@ ath_raw_xmit(struct ieee80211_node *ni, 
        return 0;
 bad2:
        ATH_TXBUF_LOCK(sc);
-       STAILQ_INSERT_HEAD(&sc->sc_txbuf, bf, bf_list);
+       TAILQ_INSERT_HEAD(&sc->sc_txbuf, bf, bf_list);
        ATH_TXBUF_UNLOCK(sc);
 bad:
        ifp->if_oerrors++;

Modified: head/sys/dev/ath/if_athvar.h
==============================================================================
--- head/sys/dev/ath/if_athvar.h        Tue Nov  8 15:38:21 2011        
(r227343)
+++ head/sys/dev/ath/if_athvar.h        Tue Nov  8 17:08:12 2011        
(r227344)
@@ -170,7 +170,7 @@ struct ath_node {
 #define        ATH_RSSI(x)             ATH_EP_RND(x, HAL_RSSI_EP_MULTIPLIER)
 
 struct ath_buf {
-       STAILQ_ENTRY(ath_buf)   bf_list;
+       TAILQ_ENTRY(ath_buf)    bf_list;
        struct ath_buf *        bf_next;        /* next buffer in the aggregate 
*/
        int                     bf_nseg;
        uint16_t                bf_txflags;     /* tx descriptor flags */
@@ -239,7 +239,7 @@ struct ath_buf {
                struct ath_rc_series bfs_rc[ATH_RC_NUM];        /* non-11n TX 
series */
        } bf_state;
 };
-typedef STAILQ_HEAD(, ath_buf) ath_bufhead;
+typedef TAILQ_HEAD(ath_bufhead_s, ath_buf) ath_bufhead;
 
 #define        ATH_BUF_BUSY    0x00000002      /* (tx) desc owned by h/w */
 
@@ -277,9 +277,10 @@ struct ath_txq {
        u_int                   axq_aggr_depth; /* how many aggregates are 
queued */
        u_int                   axq_intrcnt;    /* interrupt count */
        u_int32_t               *axq_link;      /* link ptr in last TX desc */
-       STAILQ_HEAD(, ath_buf)  axq_q;          /* transmit queue */
+       TAILQ_HEAD(axq_q_s, ath_buf)    axq_q;          /* transmit queue */
        struct mtx              axq_lock;       /* lock on q and link */
        char                    axq_name[12];   /* e.g. "ath0_txq4" */
+
        /* Per-TID traffic queue for software -> hardware TX */
        TAILQ_HEAD(axq_t_s,ath_tid)     axq_tidq;
 };
@@ -299,18 +300,20 @@ struct ath_txq {
 #define        ATH_TXQ_LOCK_ASSERT(_tq)        mtx_assert(&(_tq)->axq_lock, 
MA_OWNED)
 #define        ATH_TXQ_IS_LOCKED(_tq)          mtx_owned(&(_tq)->axq_lock)
 
+#define ATH_TXQ_INSERT_HEAD(_tq, _elm, _field) do { \
+       TAILQ_INSERT_HEAD(&(_tq)->axq_q, (_elm), _field); \
+       (_tq)->axq_depth++; \
+} while (0)
 #define ATH_TXQ_INSERT_TAIL(_tq, _elm, _field) do { \
-       STAILQ_INSERT_TAIL(&(_tq)->axq_q, (_elm), _field); \
+       TAILQ_INSERT_TAIL(&(_tq)->axq_q, (_elm), _field); \
        (_tq)->axq_depth++; \
 } while (0)
-#define ATH_TXQ_REMOVE_HEAD(_tq, _field) do { \
-       STAILQ_REMOVE_HEAD(&(_tq)->axq_q, _field); \
+#define ATH_TXQ_REMOVE(_tq, _elm, _field) do { \
+       TAILQ_REMOVE(&(_tq)->axq_q, _elm, _field); \
        (_tq)->axq_depth--; \
 } while (0)
 /* NB: this does not do the "head empty check" that STAILQ_LAST does */
-#define        ATH_TXQ_LAST(_tq) \
-       ((struct ath_buf *)(void *) \
-        ((char *)((_tq)->axq_q.stqh_last) - __offsetof(struct ath_buf, 
bf_list)))
+#define        ATH_TXQ_LAST(_tq, _field)       TAILQ_LAST(&(_tq)->axq_q, 
_field)
 
 struct ath_vap {
        struct ieee80211vap av_vap;     /* base class */
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to