summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorcube <cube@NetBSD.org>2007-09-24 13:17:53 +0000
committercube <cube@NetBSD.org>2007-09-24 13:17:53 +0000
commit9d4a2bf2135a63d667c64c2ea25b8aa8a8537b33 (patch)
tree6461d9ba09a64eb0365931423410a3d9310170f4 /sys/dev/pci
parent5b396aa2c05ae81de46a6ce45fe0f2960bc87721 (diff)
- If the chip doesn't support jumbo frames, don't use bus_dmamap_load_mbuf
which expects a properly filled mbuf chain, but bus_dmamap_load for the mbuf storage space instead. - If the chip supports jumbo frames + keep track of which RX descriptor uses which jumbo mbuf buffer, so that we can rewrite the physaddr field of the descriptor later, as it might be partially overwritten by the hw + when we're out of jumbo mbufs, and if the packet is small enough, copy it into a cluster mbuf Those changes make my nfe(4) stable in both cases (defining NFE_NO_JUMBO for the first one).
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/if_nfe.c59
-rw-r--r--sys/dev/pci/if_nfevar.h3
2 files changed, 42 insertions, 20 deletions
diff --git a/sys/dev/pci/if_nfe.c b/sys/dev/pci/if_nfe.c
index 967782c1345..203bc23788f 100644
--- a/sys/dev/pci/if_nfe.c
+++ b/sys/dev/pci/if_nfe.c
@@ -1,4 +1,4 @@
-/* $NetBSD: if_nfe.c,v 1.18 2007/09/24 13:11:08 cube Exp $ */
+/* $NetBSD: if_nfe.c,v 1.19 2007/09/24 13:17:53 cube Exp $ */
/* $OpenBSD: if_nfe.c,v 1.52 2006/03/02 09:04:00 jsg Exp $ */
/*-
@@ -21,7 +21,7 @@
/* Driver for NVIDIA nForce MCP Fast Ethernet and Gigabit Ethernet */
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_nfe.c,v 1.18 2007/09/24 13:11:08 cube Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_nfe.c,v 1.19 2007/09/24 13:17:53 cube Exp $");
#include "opt_inet.h"
#include "bpfilter.h"
@@ -94,7 +94,7 @@ void nfe_start(struct ifnet *);
void nfe_watchdog(struct ifnet *);
int nfe_init(struct ifnet *);
void nfe_stop(struct ifnet *, int);
-struct nfe_jbuf *nfe_jalloc(struct nfe_softc *);
+struct nfe_jbuf *nfe_jalloc(struct nfe_softc *, int);
void nfe_jfree(struct mbuf *, void *, size_t, void *);
int nfe_jpool_alloc(struct nfe_softc *);
void nfe_jpool_free(struct nfe_softc *);
@@ -765,18 +765,34 @@ nfe_rxeof(struct nfe_softc *sc)
}
if (sc->sc_flags & NFE_USE_JUMBO) {
- if ((jbuf = nfe_jalloc(sc)) == NULL) {
- m_freem(mnew);
- ifp->if_ierrors++;
- goto skip;
- }
- MEXTADD(mnew, jbuf->buf, NFE_JBYTES, 0, nfe_jfree, sc);
+ physaddr =
+ sc->rxq.jbuf[sc->rxq.jbufmap[i]].physaddr;
+ if ((jbuf = nfe_jalloc(sc, i)) == NULL) {
+ if (len > MCLBYTES) {
+ m_freem(mnew);
+ ifp->if_ierrors++;
+ goto skip1;
+ }
+ MCLGET(mnew, M_DONTWAIT);
+ if ((mnew->m_flags & M_EXT) == 0) {
+ m_freem(mnew);
+ ifp->if_ierrors++;
+ goto skip1;
+ }
- bus_dmamap_sync(sc->sc_dmat, sc->rxq.jmap,
- mtod(data->m, char *) - (char *)sc->rxq.jpool,
- NFE_JBYTES, BUS_DMASYNC_POSTREAD);
+ memcpy(mtod(mnew, void *),
+ mtod(data->m, const void *), len);
+ m = mnew;
+ goto mbufcopied;
+ } else {
+ MEXTADD(mnew, jbuf->buf, NFE_JBYTES, 0, nfe_jfree, sc);
- physaddr = jbuf->physaddr;
+ bus_dmamap_sync(sc->sc_dmat, sc->rxq.jmap,
+ mtod(data->m, char *) - (char *)sc->rxq.jpool,
+ NFE_JBYTES, BUS_DMASYNC_POSTREAD);
+
+ physaddr = jbuf->physaddr;
+ }
} else {
MCLGET(mnew, M_DONTWAIT);
if ((mnew->m_flags & M_EXT) == 0) {
@@ -789,14 +805,15 @@ nfe_rxeof(struct nfe_softc *sc)
data->map->dm_mapsize, BUS_DMASYNC_POSTREAD);
bus_dmamap_unload(sc->sc_dmat, data->map);
- error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map,
- mnew, BUS_DMA_READ | BUS_DMA_NOWAIT);
+ error = bus_dmamap_load(sc->sc_dmat, data->map,
+ mtod(mnew, void *), MCLBYTES, NULL,
+ BUS_DMA_READ | BUS_DMA_NOWAIT);
if (error != 0) {
m_freem(mnew);
/* try to reload the old mbuf */
- error = bus_dmamap_load_mbuf(sc->sc_dmat,
- data->map, data->m,
+ error = bus_dmamap_load(sc->sc_dmat, data->map,
+ mtod(data->m, void *), MCLBYTES, NULL,
BUS_DMA_READ | BUS_DMA_NOWAIT);
if (error != 0) {
/* very unlikely that it will fail.. */
@@ -816,6 +833,7 @@ nfe_rxeof(struct nfe_softc *sc)
m = data->m;
data->m = mnew;
+mbufcopied:
/* finalize mbuf */
m->m_pkthdr.len = m->m_len = len;
m->m_pkthdr.rcvif = ifp;
@@ -853,6 +871,7 @@ nfe_rxeof(struct nfe_softc *sc)
ifp->if_ipackets++;
(*ifp->if_input)(ifp, m);
+skip1:
/* update mapping address in h/w descriptor */
if (sc->sc_flags & NFE_40BIT_ADDR) {
#if defined(__LP64__)
@@ -1371,7 +1390,7 @@ nfe_alloc_rx_ring(struct nfe_softc *sc, struct nfe_rx_ring *ring)
}
if (sc->sc_flags & NFE_USE_JUMBO) {
- if ((jbuf = nfe_jalloc(sc)) == NULL) {
+ if ((jbuf = nfe_jalloc(sc, i)) == NULL) {
printf("%s: could not allocate jumbo buffer\n",
sc->sc_dev.dv_xname);
goto fail;
@@ -1492,13 +1511,15 @@ nfe_free_rx_ring(struct nfe_softc *sc, struct nfe_rx_ring *ring)
}
struct nfe_jbuf *
-nfe_jalloc(struct nfe_softc *sc)
+nfe_jalloc(struct nfe_softc *sc, int i)
{
struct nfe_jbuf *jbuf;
jbuf = SLIST_FIRST(&sc->rxq.jfreelist);
if (jbuf == NULL)
return NULL;
+ sc->rxq.jbufmap[i] =
+ ((char *)jbuf->buf - (char *)sc->rxq.jpool) / NFE_JBYTES;
SLIST_REMOVE_HEAD(&sc->rxq.jfreelist, jnext);
return jbuf;
}
diff --git a/sys/dev/pci/if_nfevar.h b/sys/dev/pci/if_nfevar.h
index cd10a3f390b..368cedf5964 100644
--- a/sys/dev/pci/if_nfevar.h
+++ b/sys/dev/pci/if_nfevar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: if_nfevar.h,v 1.2 2007/03/04 06:02:22 christos Exp $ */
+/* $NetBSD: if_nfevar.h,v 1.3 2007/09/24 13:17:54 cube Exp $ */
/* $OpenBSD: if_nfevar.h,v 1.11 2006/02/19 13:57:02 damien Exp $ */
/*-
@@ -59,6 +59,7 @@ struct nfe_rx_ring {
void * jpool;
struct nfe_rx_data data[NFE_RX_RING_COUNT];
struct nfe_jbuf jbuf[NFE_JPOOL_COUNT];
+ int jbufmap[NFE_RX_RING_COUNT];
SLIST_HEAD(, nfe_jbuf) jfreelist;
int bufsz;
int cur;