summaryrefslogtreecommitdiffstats
path: root/sys/dev/ti
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>1999-06-19 00:36:56 +0000
committerwpaul <wpaul@FreeBSD.org>1999-06-19 00:36:56 +0000
commit2f586076cdac59250332cc3e33017bc718a6c8b4 (patch)
tree5aaf2350b53ef087e74cf0a79590df646128f2dc /sys/dev/ti
parent517a8eacaf9de8fce05ee46d0bb7f0f1d4c692b9 (diff)
downloadFreeBSD-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>
Diffstat (limited to 'sys/dev/ti')
-rw-r--r--sys/dev/ti/if_ti.c16
-rw-r--r--sys/dev/ti/if_tireg.h3
2 files changed, 15 insertions, 4 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;
};
/*
OpenPOWER on IntegriCloud