summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2015-10-06 15:21:17 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2015-10-06 15:21:17 +0000
commit2b7e1ba212e541c909cf6e78db703c91b697a46c (patch)
tree07be7f39f7443e286238d81aa4ff58c36fb9d5a9 /sys/dev
parentc4c451df192404de602af70cb6a21bc3d42cee30 (diff)
Make sure that tx_buffer->next_eop is properly set before we bump the number
of available descriptors, such that the interrupt handler doesn't attempt to complete partially initialized descriptors. Seems to fix the watchdog timeouts reported by various people. Tested by Mattieu Baptiste and Gregor Best. ok mikeb@
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pci/if_em.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/sys/dev/pci/if_em.c b/sys/dev/pci/if_em.c
index 94d906b6572..9b860d5a72f 100644
--- a/sys/dev/pci/if_em.c
+++ b/sys/dev/pci/if_em.c
@@ -31,7 +31,7 @@ POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
-/* $OpenBSD: if_em.c,v 1.306 2015/09/30 11:25:08 kettenis Exp $ */
+/* $OpenBSD: if_em.c,v 1.307 2015/10/06 15:21:16 kettenis Exp $ */
/* $FreeBSD: if_em.c,v 1.46 2004/09/29 18:28:28 mlaier Exp $ */
#include <dev/pci/if_em.h>
@@ -1210,12 +1210,6 @@ em_encap(struct em_softc *sc, struct mbuf *m_head)
}
}
- sc->next_avail_tx_desc = i;
- if (sc->pcix_82544)
- atomic_sub_int(&sc->num_tx_desc_avail, txd_used);
- else
- atomic_sub_int(&sc->num_tx_desc_avail, map->dm_nsegs);
-
#if NVLAN > 0
/* Find out if we are in VLAN mode */
if (m_head->m_flags & M_VLANTAG) {
@@ -1249,6 +1243,14 @@ em_encap(struct em_softc *sc, struct mbuf *m_head)
tx_buffer = &sc->tx_buffer_area[first];
tx_buffer->next_eop = last;
+ membar_producer();
+
+ sc->next_avail_tx_desc = i;
+ if (sc->pcix_82544)
+ atomic_sub_int(&sc->num_tx_desc_avail, txd_used);
+ else
+ atomic_sub_int(&sc->num_tx_desc_avail, map->dm_nsegs);
+
/*
* Advance the Transmit Descriptor Tail (Tdt),
* this tells the E1000 that this frame is
@@ -2378,6 +2380,8 @@ em_transmit_checksum_setup(struct em_softc *sc, struct mbuf *mp,
tx_buffer->m_head = NULL;
tx_buffer->next_eop = -1;
+ membar_producer();
+
if (++curr_txd == sc->num_tx_desc)
curr_txd = 0;
@@ -2403,6 +2407,8 @@ em_txeof(struct em_softc *sc)
if (sc->num_tx_desc_avail == sc->num_tx_desc)
return;
+ membar_consumer();
+
first = sc->next_tx_to_clean;
tx_desc = &sc->tx_desc_base[first];
tx_buffer = &sc->tx_buffer_area[first];