summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorDamien Bergamini <damien@cvs.openbsd.org>2006-11-10 20:46:59 +0000
committerDamien Bergamini <damien@cvs.openbsd.org>2006-11-10 20:46:59 +0000
commite7f3740f4f12ea46b396b24d250b2eb76780e1d2 (patch)
tree1e2659809d63a2cbf54e1771d26470413b6fa74e /sys
parent692f24d9c2b538d9e0cde74f8454eb56d16f2cb1 (diff)
Defer setting of the valid bit in the first TX descriptor after
all descriptors have been setup. Otherwise, hardware may start processing descriptors faster than us and crap out. Fixes "watchdog timeout" errors. Original idea from Matthew Dillon @DragonFly. ok deraadt@ jsg@ wim@ tested by many
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pci/if_nfe.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/sys/dev/pci/if_nfe.c b/sys/dev/pci/if_nfe.c
index 35e6871321b..5baa9d72fd1 100644
--- a/sys/dev/pci/if_nfe.c
+++ b/sys/dev/pci/if_nfe.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_nfe.c,v 1.65 2006/11/05 20:15:37 brad Exp $ */
+/* $OpenBSD: if_nfe.c,v 1.66 2006/11/10 20:46:58 damien Exp $ */
/*-
* Copyright (c) 2006 Damien Bergamini <damien.bergamini@free.fr>
@@ -883,13 +883,13 @@ nfe_encap(struct nfe_softc *sc, struct mbuf *m0)
struct nfe_desc64 *desc64;
struct nfe_tx_data *data;
bus_dmamap_t map;
- uint16_t flags = NFE_TX_VALID;
+ uint16_t flags = 0;
#if NVLAN > 0
uint32_t vtag = 0;
#endif
- int error, i;
+ int error, i, first = sc->txq.cur;
- map = sc->txq.data[sc->txq.cur].map;
+ map = sc->txq.data[first].map;
error = bus_dmamap_load_mbuf(sc->sc_dmat, map, m0, BUS_DMA_NOWAIT);
if (error != 0) {
@@ -942,28 +942,44 @@ nfe_encap(struct nfe_softc *sc, struct mbuf *m0)
desc32->flags = htole16(flags);
}
- /* csum flags and vtag belong to the first fragment only */
if (map->dm_nsegs > 1) {
+ /*
+ * Checksum flags and vtag belong to the first fragment
+ * only.
+ */
flags &= ~(NFE_TX_IP_CSUM | NFE_TX_TCP_CSUM);
#if NVLAN > 0
vtag = 0;
#endif
+ /*
+ * Setting of the valid bit in the first descriptor is
+ * deferred until the whole chain is fully setup.
+ */
+ flags |= NFE_TX_VALID;
}
sc->txq.queued++;
sc->txq.cur = (sc->txq.cur + 1) % NFE_TX_RING_COUNT;
}
- /* the whole mbuf chain has been DMA mapped, fix last descriptor */
+ /* the whole mbuf chain has been setup */
if (sc->sc_flags & NFE_40BIT_ADDR) {
+ /* fix last descriptor */
flags |= NFE_TX_LASTFRAG_V2;
desc64->flags = htole16(flags);
+
+ /* finally, set the valid bit in the first descriptor */
+ sc->txq.desc64[first].flags |= htole16(NFE_TX_VALID);
} else {
+ /* fix last descriptor */
if (sc->sc_flags & NFE_JUMBO_SUP)
flags |= NFE_TX_LASTFRAG_V2;
else
flags |= NFE_TX_LASTFRAG_V1;
desc32->flags = htole16(flags);
+
+ /* finally, set the valid bit in the first descriptor */
+ sc->txq.desc32[first].flags |= htole16(NFE_TX_VALID);
}
data->m = m0;