summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorBrad Smith <brad@cvs.openbsd.org>2006-11-19 17:35:47 +0000
committerBrad Smith <brad@cvs.openbsd.org>2006-11-19 17:35:47 +0000
commitdb540f3de85e06e1fe471f5b0d25ff1d1c72c02c (patch)
tree7abfc0e79fbd596d31fdb7631064962866cd472b /sys
parent81b4a38c387815f57591999b4a9fb600bf745dd4 (diff)
In bnx_start, check the used_tx_bd count rather than the descriptors
mbuf pointer to see if the transmit ring is full. The mbuf pointer is set only in the last descriptor of a multi-descriptor packet. By relying on the mbuf pointers of the earlier descriptors, the driver would sometimes overwrite a descriptor belonging to a packet that wasn't completed yet. Also, tx_chain_prod wasn't updated inside the loop, causing the wrong descriptor to be checked after the first iteration. The upshot of all this was the loss of some transmitted packets at medium to high packet rates. In bnx_tx_encap, remove a couple of old statements that shuffled around the tx_mbuf_map pointers. These now correspond 1-to-1 with the transmit descriptors, and they are not supposed to be changed. Correct a couple of inaccurate comments. From jdp@FreeBSD
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pci/if_bnx.c28
1 files changed, 14 insertions, 14 deletions
diff --git a/sys/dev/pci/if_bnx.c b/sys/dev/pci/if_bnx.c
index 7f654397dca..42d6e1814b1 100644
--- a/sys/dev/pci/if_bnx.c
+++ b/sys/dev/pci/if_bnx.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bnx.c,v 1.32 2006/10/26 00:05:07 brad Exp $ */
+/* $OpenBSD: if_bnx.c,v 1.33 2006/11/19 17:35:46 brad Exp $ */
/*-
* Copyright (c) 2006 Broadcom Corporation
@@ -4395,17 +4395,14 @@ bnx_tx_encap(struct bnx_softc *sc, struct mbuf **m_head)
__FUNCTION__, prod, chain_prod, prod_bseq);
/*
- * Ensure that the map for this transmission
- * is placed at the array index of the last
- * descriptor in this chain. This is done
- * because a single map is used for all
- * segments of the mbuf and we don't want to
- * delete the map before all of the segments
- * have been freed.
+ * Ensure that the mbuf pointer for this
+ * transmission is placed at the array
+ * index of the last descriptor in this
+ * chain. This is done because a single
+ * map is used for all segments of the mbuf
+ * and we don't want to unload the map before
+ * all of the segments have been freed.
*/
- sc->tx_mbuf_map[TX_CHAIN_IDX(sc->tx_prod)] =
- sc->tx_mbuf_map[chain_prod];
- sc->tx_mbuf_map[chain_prod] = map;
sc->tx_mbuf_ptr[chain_prod] = m0;
sc->used_tx_bd += map->dm_nsegs;
@@ -4417,7 +4414,7 @@ bnx_tx_encap(struct bnx_softc *sc, struct mbuf **m_head)
DBRUN(BNX_VERBOSE_SEND, bnx_dump_tx_mbuf_chain(sc, chain_prod,
map_arg.maxsegs));
- /* prod still points the last used tx_bd at this point. */
+ /* prod points to the next free tx_bd at this point. */
sc->tx_prod = prod;
sc->tx_prod_bseq = prod_bseq;
@@ -4453,8 +4450,11 @@ bnx_start(struct ifnet *ifp)
"tx_chain_prod = %04X, tx_prod_bseq = 0x%08X\n",
__FUNCTION__, tx_prod, tx_chain_prod, sc->tx_prod_bseq);
- /* Keep adding entries while there is space in the ring. */
- while (sc->tx_mbuf_ptr[tx_chain_prod] == NULL) {
+ /*
+ * Keep adding entries while there is space in the ring. We keep
+ * BNX_TX_SLACK_SPACE entries unused at all times.
+ */
+ while (sc->used_tx_bd < USABLE_TX_BD - BNX_TX_SLACK_SPACE) {
/* Check for any frames to send. */
IFQ_POLL(&ifp->if_snd, m_head);
if (m_head == NULL)