diff options
author | adrian <adrian@FreeBSD.org> | 2012-06-14 00:51:53 +0000 |
---|---|---|
committer | adrian <adrian@FreeBSD.org> | 2012-06-14 00:51:53 +0000 |
commit | a65b3dd5896112ac53c1e9c96fcd55cda29a0a99 (patch) | |
tree | 6e4a1c7a629deb8deff7aaaa22359b8edc84dddb | |
parent | d0039ee2cf0f8e40d536d4f57fad8d221e152aa8 (diff) | |
download | FreeBSD-src-a65b3dd5896112ac53c1e9c96fcd55cda29a0a99.zip FreeBSD-src-a65b3dd5896112ac53c1e9c96fcd55cda29a0a99.tar.gz |
Implement a global (all non-mgmt traffic) TX ath_buf limitation when
ath_start() is called.
This (defaults to 10 frames) gives for a little headway in the TX ath_buf
allocation, so buffer cloning is still possible.
This requires a lot omre experimenting and tuning.
It also doesn't stop a node/TID from consuming all of the available
ath_buf's, especially when the node is going through high packet loss
or only talking at a low TX rate. It also doesn't stop a paused TID
from taking all of the ath_bufs. I'll look at fixing that up in subsequent
commits.
PR: kern/168170
-rw-r--r-- | sys/dev/ath/if_ath.c | 51 | ||||
-rw-r--r-- | sys/dev/ath/if_ath_sysctl.c | 7 | ||||
-rw-r--r-- | sys/dev/ath/if_athvar.h | 1 |
3 files changed, 52 insertions, 7 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; + } + } } /* diff --git a/sys/dev/ath/if_ath_sysctl.c b/sys/dev/ath/if_ath_sysctl.c index 6060abb..ff75888 100644 --- a/sys/dev/ath/if_ath_sysctl.c +++ b/sys/dev/ath/if_ath_sysctl.c @@ -374,8 +374,8 @@ ath_sysctl_txagg(SYSCTL_HANDLER_ARGS) t++; } ATH_TXBUF_UNLOCK(sc); - printf("Total TX buffers: %d; Total TX buffers busy: %d\n", - t, i); + printf("Total TX buffers: %d; Total TX buffers busy: %d (%d)\n", + t, i, sc->sc_txbuf_cnt); i = t = 0; ATH_TXBUF_LOCK(sc); @@ -620,12 +620,11 @@ ath_sysctlattach(struct ath_softc *sc) "tid_hwq_hi", CTLFLAG_RW, &sc->sc_tid_hwq_hi, 0, ""); -#if 0 SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "txq_data_minfree", CTLFLAG_RW, &sc->sc_txq_data_minfree, 0, "Minimum free buffers before adding a data frame" " to the TX queue"); -#endif + SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "txq_mcastq_maxdepth", CTLFLAG_RW, &sc->sc_txq_mcastq_maxdepth, 0, diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h index 407e997..d58c83f 100644 --- a/sys/dev/ath/if_athvar.h +++ b/sys/dev/ath/if_athvar.h @@ -501,6 +501,7 @@ struct ath_softc { struct ath_descdma sc_txdma; /* TX descriptors */ ath_bufhead sc_txbuf; /* transmit buffer */ + int sc_txbuf_cnt; /* how many buffers avail */ struct ath_descdma sc_txdma_mgmt; /* mgmt TX descriptors */ ath_bufhead sc_txbuf_mgmt; /* mgmt transmit buffer */ struct mtx sc_txbuflock; /* txbuf lock */ |