summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authoradrian <adrian@FreeBSD.org>2013-05-18 18:27:53 +0000
committeradrian <adrian@FreeBSD.org>2013-05-18 18:27:53 +0000
commit83ab6e624a00a45979410bd5a03a0fbb6079df3e (patch)
tree982dc2f330d7b1ede341773940926f2f2a2705a4 /sys/dev
parent6c177c4e75df3a6afa03ccc9e7410b89b8dd1f5c (diff)
downloadFreeBSD-src-83ab6e624a00a45979410bd5a03a0fbb6079df3e.zip
FreeBSD-src-83ab6e624a00a45979410bd5a03a0fbb6079df3e.tar.gz
Be (very) careful about how to add more TX DMA work.
The list-based DMA engine has the following behaviour: * When the DMA engine is in the init state, you can write the first descriptor address to the QCU TxDP register and it will work. * Then when it hits the end of the list (ie, it either hits a NULL link pointer, OR it hits a descriptor with VEOL set) the QCU stops, and the TxDP points to the last descriptor that was transmitted. * Then when you want to transmit a new frame, you can then either: + write the head of the new list into TxDP, or + you write the head of the new list into the link pointer of the last completed descriptor (ie, where TxDP points), then kick TxE to restart transmission on that QCU> * The hardware then will re-read the descriptor to pick up the link pointer and then jump to that. Now, the quirks: * If you write a TxDP when there's been no previous TxDP (ie, it's 0), it works. * If you write a TxDP in any other instance, the TxDP write may actually fail. Thus, when you start transmission, it will re-read the last transmitted descriptor to get the link pointer, NOT just start a new transmission. So the correct thing to do here is: * ALWAYS use the holding descriptor (ie, the last transmitted descriptor that we've kept safe) and use the link pointer in _THAT_ to transmit the next frame. * NEVER write to the TxDP after you've done the initial write. * .. also, don't do this whilst you're also resetting the NIC. With this in mind, the following patch does basically the above. * Since this encapsulates Sam's issues with the QCU behaviour w/ TDMA, kill the TDMA special case and replace it with the above. * Add a new TXQ flag - PUTRUNNING - which indicates that we've started DMA. * Clear that flag when DMA has been shutdown. * Ensure that we're not restarting DMA with PUTRUNNING enabled. * Fix the link pointer logic during TXQ drain - we should always ensure the link pointer does point to something if there's a list of frames. Having it be NULL as an indication that DMA has finished or during a reset causes trouble. Now, given all of this, i want to nuke axq_link from orbit. There's now HAL methods to get and set the link pointer of a descriptor, so what we should do instead is to update the right link pointer. * If there's a holding descriptor and an empty TXQ list, set the link pointer of said holding descriptor to the new frame. * If there's a non-empty TXQ list, set the link pointer of the last descriptor in the list to the new frame. * Nuke axq_link from orbit. Note: * The AR9380 doesn't need this. FIFO TX writes are atomic. As long as we don't append to a list of frames that we've already passed to the hardware, all of the above doesn't apply. The holding descriptor stuff is still needed to ensure the hardware can re-read a completed descriptor to move onto the next one, but we restart DMA by pushing in a new FIFO entry into the TX QCU. That doesn't require any real gymnastics. Tested: * AR5210, AR5211, AR5212, AR5416, AR9380 - STA mode.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ath/if_ath.c35
-rw-r--r--sys/dev/ath/if_ath_beacon.c12
-rw-r--r--sys/dev/ath/if_ath_misc.h2
-rw-r--r--sys/dev/ath/if_ath_tx.c292
-rw-r--r--sys/dev/ath/if_athvar.h3
5 files changed, 195 insertions, 149 deletions
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c
index b402e76..f5cae0e 100644
--- a/sys/dev/ath/if_ath.c
+++ b/sys/dev/ath/if_ath.c
@@ -4620,6 +4620,8 @@ ath_tx_stopdma(struct ath_softc *sc, struct ath_txq *txq)
{
struct ath_hal *ah = sc->sc_ah;
+ ATH_TXQ_LOCK_ASSERT(txq);
+
DPRINTF(sc, ATH_DEBUG_RESET,
"%s: tx queue [%u] %p, active=%d, hwpending=%d, flags 0x%08x, "
"link %p, holdingbf=%p\n",
@@ -4633,6 +4635,8 @@ ath_tx_stopdma(struct ath_softc *sc, struct ath_txq *txq)
txq->axq_holdingbf);
(void) ath_hal_stoptxdma(ah, txq->axq_qnum);
+ /* We've stopped TX DMA, so mark this as stopped. */
+ txq->axq_flags &= ~ATH_TXQ_PUTRUNNING;
#ifdef ATH_DEBUG
if ((sc->sc_debug & ATH_DEBUG_RESET)
@@ -4658,17 +4662,25 @@ ath_stoptxdma(struct ath_softc *sc)
__func__, sc->sc_bhalq,
(caddr_t)(uintptr_t) ath_hal_gettxbuf(ah, sc->sc_bhalq),
NULL);
+
+ /* stop the beacon queue */
(void) ath_hal_stoptxdma(ah, sc->sc_bhalq);
- for (i = 0; i < HAL_NUM_TX_QUEUES; i++)
- if (ATH_TXQ_SETUP(sc, i))
+
+ /* Stop the data queues */
+ for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
+ if (ATH_TXQ_SETUP(sc, i)) {
+ ATH_TXQ_LOCK(&sc->sc_txq[i]);
ath_tx_stopdma(sc, &sc->sc_txq[i]);
+ ATH_TXQ_UNLOCK(&sc->sc_txq[i]);
+ }
+ }
}
return 1;
}
#ifdef ATH_DEBUG
-static void
+void
ath_tx_dump(struct ath_softc *sc, struct ath_txq *txq)
{
struct ath_hal *ah = sc->sc_ah;
@@ -4702,6 +4714,7 @@ ath_legacy_tx_drain(struct ath_softc *sc, ATH_RESET_TYPE reset_type)
#endif
struct ifnet *ifp = sc->sc_ifp;
int i;
+ struct ath_buf *bf_last;
(void) ath_stoptxdma(sc);
@@ -4727,10 +4740,20 @@ ath_legacy_tx_drain(struct ath_softc *sc, ATH_RESET_TYPE reset_type)
*/
ath_txq_freeholdingbuf(sc, &sc->sc_txq[i]);
/*
- * Reset the link pointer to NULL; there's
- * no frames to chain DMA to.
+ * Setup the link pointer to be the
+ * _last_ buffer/descriptor in the list.
+ * If there's nothing in the list, set it
+ * to NULL.
*/
- sc->sc_txq[i].axq_link = NULL;
+ bf_last = ATH_TXQ_LAST(&sc->sc_txq[i],
+ axq_q_s);
+ if (bf_last != NULL) {
+ ath_hal_gettxdesclinkptr(ah,
+ bf_last->bf_lastds,
+ &sc->sc_txq[i].axq_link);
+ } else {
+ sc->sc_txq[i].axq_link = NULL;
+ }
ATH_TXQ_UNLOCK(&sc->sc_txq[i]);
} else
ath_tx_draintxq(sc, &sc->sc_txq[i]);
diff --git a/sys/dev/ath/if_ath_beacon.c b/sys/dev/ath/if_ath_beacon.c
index b58864c..11b0426 100644
--- a/sys/dev/ath/if_ath_beacon.c
+++ b/sys/dev/ath/if_ath_beacon.c
@@ -642,6 +642,7 @@ ath_beacon_cabq_start_edma(struct ath_softc *sc)
/* Push the first entry into the hardware */
ath_hal_puttxbuf(sc->sc_ah, cabq->axq_qnum, bf->bf_daddr);
+ cabq->axq_flags |= ATH_TXQ_PUTRUNNING;
/* NB: gated by beacon so safe to start here */
ath_hal_txstart(sc->sc_ah, cabq->axq_qnum);
@@ -661,6 +662,7 @@ ath_beacon_cabq_start_legacy(struct ath_softc *sc)
/* Push the first entry into the hardware */
ath_hal_puttxbuf(sc->sc_ah, cabq->axq_qnum, bf->bf_daddr);
+ cabq->axq_flags |= ATH_TXQ_PUTRUNNING;
/* NB: gated by beacon so safe to start here */
ath_hal_txstart(sc->sc_ah, cabq->axq_qnum);
@@ -736,6 +738,16 @@ ath_beacon_generate(struct ath_softc *sc, struct ieee80211vap *vap)
* frames from a different vap.
* XXX could be slow causing us to miss DBA
*/
+ /*
+ * XXX TODO: this doesn't stop CABQ DMA - it assumes
+ * that since we're about to transmit a beacon, we've
+ * already stopped transmitting on the CABQ. But this
+ * doesn't at all mean that the CABQ DMA QCU will
+ * accept a new TXDP! So what, should we do a DMA
+ * stop? What if it fails?
+ *
+ * More thought is required here.
+ */
ath_tx_draintxq(sc, cabq);
}
}
diff --git a/sys/dev/ath/if_ath_misc.h b/sys/dev/ath/if_ath_misc.h
index 965ab9f..00a476e 100644
--- a/sys/dev/ath/if_ath_misc.h
+++ b/sys/dev/ath/if_ath_misc.h
@@ -125,6 +125,8 @@ extern void ath_tx_update_tim(struct ath_softc *sc,
extern void ath_start(struct ifnet *ifp);
extern void ath_start_task(void *arg, int npending);
+extern void ath_tx_dump(struct ath_softc *sc, struct ath_txq *txq);
+
/*
* Kick the frame TX task.
*/
diff --git a/sys/dev/ath/if_ath_tx.c b/sys/dev/ath/if_ath_tx.c
index 5f8cfdf..e394205 100644
--- a/sys/dev/ath/if_ath_tx.c
+++ b/sys/dev/ath/if_ath_tx.c
@@ -744,6 +744,7 @@ ath_tx_handoff_hw(struct ath_softc *sc, struct ath_txq *txq,
struct ath_buf *bf)
{
struct ath_hal *ah = sc->sc_ah;
+ struct ath_buf *bf_first;
/*
* Insert the frame on the outbound list and pass it on
@@ -759,6 +760,13 @@ ath_tx_handoff_hw(struct ath_softc *sc, struct ath_txq *txq,
KASSERT(txq->axq_qnum != ATH_TXQ_SWQ,
("ath_tx_handoff_hw called for mcast queue"));
+ /*
+ * XXX racy, should hold the PCU lock when checking this,
+ * and also should ensure that the TX counter is >0!
+ */
+ KASSERT((sc->sc_inreset_cnt == 0),
+ ("%s: TX during reset?\n", __func__));
+
#if 0
/*
* This causes a LOR. Find out where the PCU lock is being
@@ -776,161 +784,141 @@ ath_tx_handoff_hw(struct ath_softc *sc, struct ath_txq *txq,
__func__, txq->axq_qnum,
(caddr_t)bf->bf_daddr, bf->bf_desc,
txq->axq_depth);
+ /* XXX axq_link needs to be set and updated! */
ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
if (bf->bf_state.bfs_aggr)
txq->axq_aggr_depth++;
- /*
- * There's no need to update axq_link; the hardware
- * is in reset and once the reset is complete, any
- * non-empty queues will simply have DMA restarted.
- */
return;
}
ATH_PCU_UNLOCK(sc);
#endif
- /* For now, so not to generate whitespace diffs */
- if (1) {
- ATH_TXQ_LOCK(txq);
-#ifdef IEEE80211_SUPPORT_TDMA
- int qbusy;
+ ATH_TXQ_LOCK(txq);
- ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
- qbusy = ath_hal_txqenabled(ah, txq->axq_qnum);
+ /*
+ * XXX TODO: if there's a holdingbf, then
+ * ATH_TXQ_PUTRUNNING should be clear.
+ *
+ * If there is a holdingbf and the list is empty,
+ * then axq_link should be pointing to the holdingbf.
+ *
+ * Otherwise it should point to the last descriptor
+ * in the last ath_buf.
+ *
+ * In any case, we should really ensure that we
+ * update the previous descriptor link pointer to
+ * this descriptor, regardless of all of the above state.
+ *
+ * For now this is captured by having axq_link point
+ * to either the holdingbf (if the TXQ list is empty)
+ * or the end of the list (if the TXQ list isn't empty.)
+ * I'd rather just kill axq_link here and do it as above.
+ */
- ATH_KTR(sc, ATH_KTR_TX, 4,
- "ath_tx_handoff: txq=%u, add bf=%p, qbusy=%d, depth=%d",
- txq->axq_qnum, bf, qbusy, txq->axq_depth);
- 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) lastds=%p depth %d\n",
- __func__, txq->axq_qnum,
- (caddr_t)bf->bf_daddr, bf->bf_desc,
- bf->bf_lastds,
- txq->axq_depth);
- ATH_KTR(sc, ATH_KTR_TX, 5,
- "ath_tx_handoff: TXDP[%u] = %p (%p) "
- "lastds=%p depth %d",
- txq->axq_qnum,
- (caddr_t)bf->bf_daddr, bf->bf_desc,
- bf->bf_lastds,
- 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);
- ATH_KTR(sc, ATH_KTR_TX, 0, "defer enable");
- }
- } 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);
- ATH_KTR(sc, ATH_KTR_TX, 5,
- "ath_tx_handoff: link[%u](%p)=%p (%p) lastds=%p",
- txq->axq_qnum, txq->axq_link,
- (caddr_t)bf->bf_daddr, bf->bf_desc,
- bf->bf_lastds);
-
- 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,
- 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__,
- txq->axq_qnum);
- ATH_KTR(sc, ATH_KTR_TX, 4,
- "ath_tx_handoff: txq[%d] restarted, bf=%p "
- "daddr=%p ds=%p",
- txq->axq_qnum,
- bf,
- (caddr_t)bf->bf_daddr,
- bf->bf_desc);
- }
- }
-#else
- ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
- ATH_KTR(sc, ATH_KTR_TX, 3,
- "ath_tx_handoff: non-tdma: txq=%u, add bf=%p "
- "depth=%d",
+ /*
+ * Append the frame to the TX queue.
+ */
+ ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
+ ATH_KTR(sc, ATH_KTR_TX, 3,
+ "ath_tx_handoff: non-tdma: txq=%u, add bf=%p "
+ "depth=%d",
+ txq->axq_qnum,
+ bf,
+ txq->axq_depth);
+
+ /*
+ * If there's a link pointer, update it.
+ *
+ * XXX we should replace this with the above logic, just
+ * to kill axq_link with fire.
+ */
+ if (txq->axq_link != NULL) {
+ *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);
+ ATH_KTR(sc, ATH_KTR_TX, 5,
+ "ath_tx_handoff: non-tdma: link[%u](%p)=%p (%p) "
+ "lastds=%d",
+ txq->axq_qnum, txq->axq_link,
+ (caddr_t)bf->bf_daddr, bf->bf_desc,
+ bf->bf_lastds);
+ }
+
+ /*
+ * If we've not pushed anything into the hardware yet,
+ * push the head of the queue into the TxDP.
+ *
+ * Once we've started DMA, there's no guarantee that
+ * updating the TxDP with a new value will actually work.
+ * So we just don't do that - if we hit the end of the list,
+ * we keep that buffer around (the "holding buffer") and
+ * re-start DMA by updating the link pointer of _that_
+ * descriptor and then restart DMA.
+ */
+ if (! (txq->axq_flags & ATH_TXQ_PUTRUNNING)) {
+ bf_first = TAILQ_FIRST(&txq->axq_q);
+ txq->axq_flags |= ATH_TXQ_PUTRUNNING;
+ ath_hal_puttxbuf(ah, txq->axq_qnum, bf_first->bf_daddr);
+ DPRINTF(sc, ATH_DEBUG_XMIT,
+ "%s: TXDP[%u] = %p (%p) depth %d\n",
+ __func__, txq->axq_qnum,
+ (caddr_t)bf_first->bf_daddr, bf_first->bf_desc,
+ txq->axq_depth);
+ ATH_KTR(sc, ATH_KTR_TX, 5,
+ "ath_tx_handoff: TXDP[%u] = %p (%p) "
+ "lastds=%p depth %d",
txq->axq_qnum,
- bf,
+ (caddr_t)bf_first->bf_daddr, bf_first->bf_desc,
+ bf_first->bf_lastds,
txq->axq_depth);
- 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);
- ATH_KTR(sc, ATH_KTR_TX, 5,
- "ath_tx_handoff: non-tdma: TXDP[%u] = %p (%p) "
- "lastds=%p depth %d",
- txq->axq_qnum,
- (caddr_t)bf->bf_daddr, bf->bf_desc,
- bf->bf_lastds,
- 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);
- ATH_KTR(sc, ATH_KTR_TX, 5,
- "ath_tx_handoff: non-tdma: link[%u](%p)=%p (%p) "
- "lastds=%d",
- txq->axq_qnum, txq->axq_link,
- (caddr_t)bf->bf_daddr, bf->bf_desc,
- bf->bf_lastds);
+ /*
+ * Ensure that the bf TXQ matches this TXQ, so later
+ * checking and holding buffer manipulation is sane.
+ */
+ if (bf->bf_state.bfs_tx_queue != txq->axq_qnum) {
+ device_printf(sc->sc_dev,
+ "%s: bf=%p, bfs_tx_queue=%d, axq_qnum=%d\n",
+ __func__,
+ bf,
+ bf->bf_state.bfs_tx_queue,
+ txq->axq_qnum);
+ }
- }
-#endif /* IEEE80211_SUPPORT_TDMA */
+ /*
+ * Track aggregate queue depth.
+ */
+ if (bf->bf_state.bfs_aggr)
+ txq->axq_aggr_depth++;
- if (bf->bf_state.bfs_tx_queue != txq->axq_qnum) {
- device_printf(sc->sc_dev,
- "%s: bf=%p, bfs_tx_queue=%d, axq_qnum=%d\n",
- __func__,
- bf,
- bf->bf_state.bfs_tx_queue,
- txq->axq_qnum);
- }
+ /*
+ * Update the link pointer.
+ */
+ ath_hal_gettxdesclinkptr(ah, bf->bf_lastds, &txq->axq_link);
- if (bf->bf_state.bfs_aggr)
- txq->axq_aggr_depth++;
- ath_hal_gettxdesclinkptr(ah, bf->bf_lastds, &txq->axq_link);
- ath_hal_txstart(ah, txq->axq_qnum);
- ATH_TXQ_UNLOCK(txq);
- ATH_KTR(sc, ATH_KTR_TX, 1,
- "ath_tx_handoff: txq=%u, txstart", txq->axq_qnum);
- }
+ /*
+ * Start DMA.
+ *
+ * If we wrote a TxDP above, DMA will start from here.
+ *
+ * If DMA is running, it'll do nothing.
+ *
+ * If the DMA engine hit the end of the QCU list (ie LINK=NULL,
+ * or VEOL) then it stops at the last transmitted write.
+ * We then append a new frame by updating the link pointer
+ * in that descriptor and then kick TxE here; it will re-read
+ * that last descriptor and find the new descriptor to transmit.
+ *
+ * This is why we keep the holding descriptor around.
+ */
+ ath_hal_txstart(ah, txq->axq_qnum);
+ ATH_TXQ_UNLOCK(txq);
+ ATH_KTR(sc, ATH_KTR_TX, 1,
+ "ath_tx_handoff: txq=%u, txstart", txq->axq_qnum);
}
/*
@@ -945,8 +933,6 @@ ath_legacy_tx_dma_restart(struct ath_softc *sc, struct ath_txq *txq)
struct ath_buf *bf, *bf_last;
ATH_TXQ_LOCK_ASSERT(txq);
- /* This is always going to be cleared, empty or not */
- txq->axq_flags &= ~ATH_TXQ_PUTPENDING;
/* XXX make this ATH_TXQ_FIRST */
bf = TAILQ_FIRST(&txq->axq_q);
@@ -955,7 +941,29 @@ ath_legacy_tx_dma_restart(struct ath_softc *sc, struct ath_txq *txq)
if (bf == NULL)
return;
- ath_hal_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
+ DPRINTF(sc, ATH_DEBUG_RESET,
+ "%s: Q%d: bf=%p, bf_last=%p, daddr=0x%08x\n",
+ __func__,
+ txq->axq_qnum,
+ bf,
+ bf_last,
+ (uint32_t) bf->bf_daddr);
+
+ if (sc->sc_debug & ATH_DEBUG_RESET)
+ ath_tx_dump(sc, txq);
+
+ /*
+ * This is called from a restart, so DMA is known to be
+ * completely stopped.
+ */
+ KASSERT((!(txq->axq_flags & ATH_TXQ_PUTRUNNING)),
+ ("%s: Q%d: called with PUTRUNNING=1\n",
+ __func__,
+ txq->axq_qnum));
+
+ ath_hal_puttxbuf(sc->sc_ah, txq->axq_qnum, bf->bf_daddr);
+ txq->axq_flags |= ATH_TXQ_PUTRUNNING;
+
ath_hal_gettxdesclinkptr(ah, bf_last->bf_lastds, &txq->axq_link);
ath_hal_txstart(ah, txq->axq_qnum);
}
diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h
index be09e82..02f6432 100644
--- a/sys/dev/ath/if_athvar.h
+++ b/sys/dev/ath/if_athvar.h
@@ -327,7 +327,8 @@ struct ath_txq {
#define ATH_TXQ_SWQ (HAL_NUM_TX_QUEUES+1) /* qnum for s/w only queue */
u_int axq_ac; /* WME AC */
u_int axq_flags;
-#define ATH_TXQ_PUTPENDING 0x0001 /* ath_hal_puttxbuf pending */
+//#define ATH_TXQ_PUTPENDING 0x0001 /* ath_hal_puttxbuf pending */
+#define ATH_TXQ_PUTRUNNING 0x0002 /* ath_hal_puttxbuf has been called */
u_int axq_depth; /* queue depth (stat only) */
u_int axq_aggr_depth; /* how many aggregates are queued */
u_int axq_intrcnt; /* interrupt count */
OpenPOWER on IntegriCloud