summaryrefslogtreecommitdiffstats
path: root/sys/dev/ath/if_ath.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/ath/if_ath.c')
-rw-r--r--sys/dev/ath/if_ath.c51
1 files changed, 48 insertions, 3 deletions
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c
index 0044949..dc7b352 100644
--- a/sys/dev/ath/if_ath.c
+++ b/sys/dev/ath/if_ath.c
@@ -2239,8 +2239,22 @@ _ath_getbuf_locked(struct ath_softc *sc, ath_buf_type_t btype)
if (bf != NULL && (bf->bf_flags & ATH_BUF_BUSY) == 0) {
if (btype == ATH_BUFTYPE_MGMT)
TAILQ_REMOVE(&sc->sc_txbuf_mgmt, bf, bf_list);
- else
+ else {
TAILQ_REMOVE(&sc->sc_txbuf, bf, bf_list);
+ sc->sc_txbuf_cnt--;
+
+ /*
+ * This shuldn't happen; however just to be
+ * safe print a warning and fudge the txbuf
+ * count.
+ */
+ if (sc->sc_txbuf_cnt < 0) {
+ device_printf(sc->sc_dev,
+ "%s: sc_txbuf_cnt < 0?\n",
+ __func__);
+ sc->sc_txbuf_cnt = 0;
+ }
+ }
} else
bf = NULL;
@@ -2367,6 +2381,7 @@ ath_start(struct ifnet *ifp)
"%s: sc_inreset_cnt > 0; bailing\n", __func__);
ATH_PCU_UNLOCK(sc);
IF_LOCK(&ifp->if_snd);
+ sc->sc_stats.ast_tx_qstop++;
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
IF_UNLOCK(&ifp->if_snd);
return;
@@ -2375,6 +2390,17 @@ ath_start(struct ifnet *ifp)
ATH_PCU_UNLOCK(sc);
for (;;) {
+ ATH_TXBUF_LOCK(sc);
+ if (sc->sc_txbuf_cnt <= sc->sc_txq_data_minfree) {
+ /* XXX increment counter? */
+ ATH_TXBUF_UNLOCK(sc);
+ IF_LOCK(&ifp->if_snd);
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ IF_UNLOCK(&ifp->if_snd);
+ break;
+ }
+ ATH_TXBUF_UNLOCK(sc);
+
/*
* Grab a TX buffer and associated resources.
*/
@@ -2883,6 +2909,7 @@ ath_desc_alloc(struct ath_softc *sc)
ath_descdma_cleanup(sc, &sc->sc_rxdma, &sc->sc_rxbuf);
return error;
}
+ sc->sc_txbuf_cnt = ath_txbuf;
error = ath_descdma_setup(sc, &sc->sc_txdma_mgmt, &sc->sc_txbuf_mgmt,
"tx_mgmt", ath_txbuf_mgmt, ATH_TXDESC);
@@ -3686,8 +3713,17 @@ ath_returnbuf_tail(struct ath_softc *sc, struct ath_buf *bf)
if (bf->bf_flags & ATH_BUF_MGMT)
TAILQ_INSERT_TAIL(&sc->sc_txbuf_mgmt, bf, bf_list);
- else
+ else {
TAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
+ sc->sc_txbuf_cnt++;
+ if (sc->sc_txbuf_cnt > ath_txbuf) {
+ device_printf(sc->sc_dev,
+ "%s: sc_txbuf_cnt > %d?\n",
+ __func__,
+ ath_txbuf);
+ sc->sc_txbuf_cnt = ath_txbuf;
+ }
+ }
}
void
@@ -3698,8 +3734,17 @@ ath_returnbuf_head(struct ath_softc *sc, struct ath_buf *bf)
if (bf->bf_flags & ATH_BUF_MGMT)
TAILQ_INSERT_HEAD(&sc->sc_txbuf_mgmt, bf, bf_list);
- else
+ else {
TAILQ_INSERT_HEAD(&sc->sc_txbuf, bf, bf_list);
+ sc->sc_txbuf_cnt++;
+ if (sc->sc_txbuf_cnt > ATH_TXBUF) {
+ device_printf(sc->sc_dev,
+ "%s: sc_txbuf_cnt > %d?\n",
+ __func__,
+ ATH_TXBUF);
+ sc->sc_txbuf_cnt = ATH_TXBUF;
+ }
+ }
}
/*
OpenPOWER on IntegriCloud