diff options
author | wpaul <wpaul@FreeBSD.org> | 1999-06-19 00:36:56 +0000 |
---|---|---|
committer | wpaul <wpaul@FreeBSD.org> | 1999-06-19 00:36:56 +0000 |
commit | 2f586076cdac59250332cc3e33017bc718a6c8b4 (patch) | |
tree | 5aaf2350b53ef087e74cf0a79590df646128f2dc | |
parent | 517a8eacaf9de8fce05ee46d0bb7f0f1d4c692b9 (diff) | |
download | FreeBSD-src-2f586076cdac59250332cc3e33017bc718a6c8b4.zip FreeBSD-src-2f586076cdac59250332cc3e33017bc718a6c8b4.tar.gz |
Add a transmit descriptor usage counter and use it to absolutely,
positively not let ti_encap() fill up the TX ring all the way and wrap
around. This fixes a potential transmit lockup where a really fast
machine (or particular TX traffic pattern) can overrun the end of the
ring.
Reported by: John Plevyak <jplevyak@inktomi.com>
-rw-r--r-- | sys/dev/ti/if_ti.c | 16 | ||||
-rw-r--r-- | sys/dev/ti/if_tireg.h | 3 | ||||
-rw-r--r-- | sys/pci/if_ti.c | 16 | ||||
-rw-r--r-- | sys/pci/if_tireg.h | 3 |
4 files changed, 30 insertions, 8 deletions
diff --git a/sys/dev/ti/if_ti.c b/sys/dev/ti/if_ti.c index 96370ed..a4af011 100644 --- a/sys/dev/ti/if_ti.c +++ b/sys/dev/ti/if_ti.c @@ -29,7 +29,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: if_ti.c,v 1.5 1999/05/09 17:07:00 peter Exp $ + * $Id: if_ti.c,v 1.6 1999/05/24 14:56:55 wpaul Exp $ */ /* @@ -128,7 +128,7 @@ #if !defined(lint) static const char rcsid[] = - "$Id: if_ti.c,v 1.5 1999/05/09 17:07:00 peter Exp $"; + "$Id: if_ti.c,v 1.6 1999/05/24 14:56:55 wpaul Exp $"; #endif /* @@ -1065,6 +1065,7 @@ static void ti_free_tx_ring(sc) static int ti_init_tx_ring(sc) struct ti_softc *sc; { + sc->ti_txcnt = 0; sc->ti_tx_saved_considx = 0; CSR_WRITE_4(sc, TI_MB_SENDPROD_IDX, 0); return(0); @@ -1920,6 +1921,7 @@ static void ti_txeof(sc) m_freem(sc->ti_cdata.ti_tx_chain[idx]); sc->ti_cdata.ti_tx_chain[idx] = NULL; } + sc->ti_txcnt--; TI_INC(sc->ti_tx_saved_considx, TI_TX_RING_CNT); ifp->if_timer = 0; } @@ -1996,7 +1998,7 @@ static int ti_encap(sc, m_head, txidx) { struct ti_tx_desc *f = NULL; struct mbuf *m; - u_int32_t frag, cur; + u_int32_t frag, cur, cnt = 0; #if NVLAN > 0 struct ifvlan *ifv = NULL; @@ -2045,8 +2047,15 @@ static int ti_encap(sc, m_head, txidx) f->ti_vlan_tag = 0; } #endif + /* + * Sanity check: avoid coming within 16 descriptors + * of the end of the ring. + */ + if ((TI_TX_RING_CNT - (sc->ti_txcnt + cnt)) < 16) + return(ENOBUFS); cur = frag; TI_INC(frag, TI_TX_RING_CNT); + cnt++; } } @@ -2062,6 +2071,7 @@ static int ti_encap(sc, m_head, txidx) else sc->ti_rdata->ti_tx_ring[cur].ti_flags |= TI_BDFLAG_END; sc->ti_cdata.ti_tx_chain[cur] = m_head; + sc->ti_txcnt += cnt; *txidx = frag; diff --git a/sys/dev/ti/if_tireg.h b/sys/dev/ti/if_tireg.h index 666c039..c79336a 100644 --- a/sys/dev/ti/if_tireg.h +++ b/sys/dev/ti/if_tireg.h @@ -29,7 +29,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: if_tireg.h,v 1.2 1999/05/03 17:44:52 wpaul Exp $ + * $Id: if_tireg.h,v 1.3 1999/05/26 23:01:50 gallatin Exp $ */ /* @@ -1151,6 +1151,7 @@ struct ti_softc { u_int32_t ti_tx_max_coal_bds; u_int32_t ti_tx_buf_ratio; int ti_if_flags; + int ti_txcnt; }; /* diff --git a/sys/pci/if_ti.c b/sys/pci/if_ti.c index 96370ed..a4af011 100644 --- a/sys/pci/if_ti.c +++ b/sys/pci/if_ti.c @@ -29,7 +29,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: if_ti.c,v 1.5 1999/05/09 17:07:00 peter Exp $ + * $Id: if_ti.c,v 1.6 1999/05/24 14:56:55 wpaul Exp $ */ /* @@ -128,7 +128,7 @@ #if !defined(lint) static const char rcsid[] = - "$Id: if_ti.c,v 1.5 1999/05/09 17:07:00 peter Exp $"; + "$Id: if_ti.c,v 1.6 1999/05/24 14:56:55 wpaul Exp $"; #endif /* @@ -1065,6 +1065,7 @@ static void ti_free_tx_ring(sc) static int ti_init_tx_ring(sc) struct ti_softc *sc; { + sc->ti_txcnt = 0; sc->ti_tx_saved_considx = 0; CSR_WRITE_4(sc, TI_MB_SENDPROD_IDX, 0); return(0); @@ -1920,6 +1921,7 @@ static void ti_txeof(sc) m_freem(sc->ti_cdata.ti_tx_chain[idx]); sc->ti_cdata.ti_tx_chain[idx] = NULL; } + sc->ti_txcnt--; TI_INC(sc->ti_tx_saved_considx, TI_TX_RING_CNT); ifp->if_timer = 0; } @@ -1996,7 +1998,7 @@ static int ti_encap(sc, m_head, txidx) { struct ti_tx_desc *f = NULL; struct mbuf *m; - u_int32_t frag, cur; + u_int32_t frag, cur, cnt = 0; #if NVLAN > 0 struct ifvlan *ifv = NULL; @@ -2045,8 +2047,15 @@ static int ti_encap(sc, m_head, txidx) f->ti_vlan_tag = 0; } #endif + /* + * Sanity check: avoid coming within 16 descriptors + * of the end of the ring. + */ + if ((TI_TX_RING_CNT - (sc->ti_txcnt + cnt)) < 16) + return(ENOBUFS); cur = frag; TI_INC(frag, TI_TX_RING_CNT); + cnt++; } } @@ -2062,6 +2071,7 @@ static int ti_encap(sc, m_head, txidx) else sc->ti_rdata->ti_tx_ring[cur].ti_flags |= TI_BDFLAG_END; sc->ti_cdata.ti_tx_chain[cur] = m_head; + sc->ti_txcnt += cnt; *txidx = frag; diff --git a/sys/pci/if_tireg.h b/sys/pci/if_tireg.h index 666c039..c79336a 100644 --- a/sys/pci/if_tireg.h +++ b/sys/pci/if_tireg.h @@ -29,7 +29,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: if_tireg.h,v 1.2 1999/05/03 17:44:52 wpaul Exp $ + * $Id: if_tireg.h,v 1.3 1999/05/26 23:01:50 gallatin Exp $ */ /* @@ -1151,6 +1151,7 @@ struct ti_softc { u_int32_t ti_tx_max_coal_bds; u_int32_t ti_tx_buf_ratio; int ti_if_flags; + int ti_txcnt; }; /* |