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.
This commit is contained in:
parent
3f3f6bc302
commit
6b349e5a86
@ -263,7 +263,7 @@ static int ath_bstuck_threshold = 4; /* max missed beacons */
|
||||
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 *vap, int item)
|
||||
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, struct ieee80211vap *vap)
|
||||
* 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, struct ieee80211vap *vap)
|
||||
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, struct ath_buf *bf)
|
||||
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, struct ath_txq *txq, int qnum)
|
||||
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, struct ath_txq *txq)
|
||||
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, struct ath_txq *txq)
|
||||
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, struct ath_txq *txq)
|
||||
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, struct ath_txq *txq)
|
||||
* 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, struct ath_txq *txq)
|
||||
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. */
|
||||
|
@ -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++;
|
||||
|
@ -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, ath_bufhead *frags,
|
||||
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, struct ath_txq *txq, struct ath_buf *bf)
|
||||
* 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, struct ath_txq *txq, struct ath_buf *bf)
|
||||
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, struct mbuf *m,
|
||||
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++;
|
||||
|
@ -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_TAIL(_tq, _elm, _field) do { \
|
||||
STAILQ_INSERT_TAIL(&(_tq)->axq_q, (_elm), _field); \
|
||||
#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_REMOVE_HEAD(_tq, _field) do { \
|
||||
STAILQ_REMOVE_HEAD(&(_tq)->axq_q, _field); \
|
||||
#define ATH_TXQ_INSERT_TAIL(_tq, _elm, _field) do { \
|
||||
TAILQ_INSERT_TAIL(&(_tq)->axq_q, (_elm), _field); \
|
||||
(_tq)->axq_depth++; \
|
||||
} while (0)
|
||||
#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 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user