Hi,
I'd much appreciate testing with gigabit speed for this one. As usual,
Please do not hesitate to send feedback and comments.
Thanks,
Logan
Index: src/sys/dev/pci/if_stge.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_stge.c,v
retrieving revision 1.52
diff -u -p -r1.52 if_stge.c
--- src/sys/dev/pci/if_stge.c 7 Dec 2009 15:31:07 -0000 1.52
+++ src/sys/dev/pci/if_stge.c 12 Dec 2010 18:15:21 -0000
@@ -93,6 +93,7 @@ void stge_stop(struct ifnet *, int);
void stge_reset(struct stge_softc *);
void stge_rxdrain(struct stge_softc *);
+void stge_fill_rx_ring(struct stge_softc *);
int stge_add_rxbuf(struct stge_softc *, int);
void stge_read_eeprom(struct stge_softc *, int, uint16_t *);
void stge_tick(void *);
@@ -291,7 +292,7 @@ stge_attach(struct device *parent, struc
/*
* Create the receive buffer DMA maps.
*/
- for (i = 0; i < STGE_NRXDESC; i++) {
+ for (i = 0; i < STGE_NRXDESC ; i++) {
if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
MCLBYTES, 0, 0, &sc->sc_rxsoft[i].ds_dmamap)) != 0) {
printf("%s: unable to create rx DMA map %d, "
@@ -385,7 +386,7 @@ stge_attach(struct device *parent, struc
#endif
IFQ_SET_MAXLEN(&ifp->if_snd, STGE_NTXDESC - 1);
IFQ_SET_READY(&ifp->if_snd);
-
+ m_clsetwms(ifp, MCLBYTES, 4, STGE_NRXDESC - 1);
ifp->if_capabilities = IFCAP_VLAN_MTU;
#if NVLAN > 0
@@ -763,13 +764,11 @@ stge_intr(void *arg)
if (isr & (IS_RxDMAComplete|IS_RFDListEnd)) {
stge_rxintr(sc);
if (isr & IS_RFDListEnd) {
- printf("%s: receive ring overflow\n",
- sc->sc_dev.dv_xname);
+ ifp->if_ierrors++;
/*
* XXX Should try to recover from this
* XXX more gracefully.
*/
- wantinit = 1;
}
}
@@ -878,7 +877,7 @@ stge_rxintr(struct stge_softc *sc)
uint64_t status;
int i, len;
- for (i = sc->sc_rxptr;; i = STGE_NEXTRX(i)) {
+ for (i = sc->sc_rx_cons; sc->sc_rx_cnt > 0; i = STGE_NEXTRX(i)) {
ds = &sc->sc_rxsoft[i];
STGE_CDRXSYNC(sc, i,
@@ -889,8 +888,15 @@ stge_rxintr(struct stge_softc *sc)
if ((status & RFD_RFDDone) == 0)
break;
+ bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0,
+ ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap);
+
+ m = ds->ds_mbuf;
+ ds->ds_mbuf = NULL;
+ sc->sc_rx_cnt--;
if (__predict_false(sc->sc_rxdiscard)) {
- STGE_INIT_RXDESC(sc, i);
+ m_freem(m);
if (status & RFD_FrameEnd) {
/* Reset our state. */
sc->sc_rxdiscard = 0;
@@ -898,30 +904,6 @@ stge_rxintr(struct stge_softc *sc)
continue;
}
- bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0,
- ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
-
- m = ds->ds_mbuf;
-
- /*
- * Add a new receive buffer to the ring.
- */
- if (stge_add_rxbuf(sc, i) != 0) {
- /*
- * Failed, throw away what we've done so
- * far, and discard the rest of the packet.
- */
- ifp->if_ierrors++;
- bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0,
- ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
- STGE_INIT_RXDESC(sc, i);
- if ((status & RFD_FrameEnd) == 0)
- sc->sc_rxdiscard = 1;
- if (sc->sc_rxhead != NULL)
- m_freem(sc->sc_rxhead);
- STGE_RXCHAIN_RESET(sc);
- continue;
- }
#ifdef DIAGNOSTIC
if (status & RFD_FrameStart) {
@@ -971,28 +953,6 @@ stge_rxintr(struct stge_softc *sc)
tailm->m_len = len - sc->sc_rxlen;
/*
- * If the packet is small enough to fit in a
- * single header mbuf, allocate one and copy
- * the data into it. This greatly reduces
- * memory consumption when we receive lots
- * of small packets.
- */
- if (stge_copy_small != 0 && len <= (MHLEN - 2)) {
- struct mbuf *nm;
- MGETHDR(nm, M_DONTWAIT, MT_DATA);
- if (nm == NULL) {
- ifp->if_ierrors++;
- m_freem(m);
- continue;
- }
- nm->m_data += 2;
- nm->m_pkthdr.len = nm->m_len = len;
- m_copydata(m, 0, len, mtod(nm, caddr_t));
- m_freem(m);
- m = nm;
- }
-
- /*
* Set the incoming checksum information for the packet.
*/
if ((status & RFD_IPDetected) &&
@@ -1030,7 +990,8 @@ stge_rxintr(struct stge_softc *sc)
}
/* Update the receive pointer. */
- sc->sc_rxptr = i;
+ sc->sc_rx_cons = i;
+ stge_fill_rx_ring(sc);
}
/*
@@ -1131,8 +1092,7 @@ int
stge_init(struct ifnet *ifp)
{
struct stge_softc *sc = ifp->if_softc;
- struct stge_descsoft *ds;
- int i, error = 0;
+ int i;
/*
* Cancel any pending I/O.
@@ -1161,26 +1121,12 @@ stge_init(struct ifnet *ifp)
* Initialize the receive descriptor and receive job
* descriptor rings.
*/
- for (i = 0; i < STGE_NRXDESC; i++) {
- ds = &sc->sc_rxsoft[i];
- if (ds->ds_mbuf == NULL) {
- if ((error = stge_add_rxbuf(sc, i)) != 0) {
- printf("%s: unable to allocate or map rx "
- "buffer %d, error = %d\n",
- sc->sc_dev.dv_xname, i, error);
- /*
- * XXX Should attempt to run with fewer receive
- * XXX buffers instead of just failing.
- */
- stge_rxdrain(sc);
- goto out;
- }
- } else
- STGE_INIT_RXDESC(sc, i);
- }
- sc->sc_rxptr = 0;
- sc->sc_rxdiscard = 0;
+ sc->sc_rx_cons = sc->sc_rx_prod = sc->sc_rx_cnt = 0;
STGE_RXCHAIN_RESET(sc);
+ for (i = 0; i < STGE_NRXDESC; i++)
+ STGE_INIT_RING_RXDESC(sc, i);
+ stge_fill_rx_ring(sc);
+ sc->sc_rxdiscard = 0;
/* Set the station address. */
if (sc->sc_stge1023) {
@@ -1219,7 +1165,7 @@ stge_init(struct ifnet *ifp)
CSR_WRITE_4(sc, STGE_RFDListPtrHi, 0); /* NOTE: 32-bit DMA */
CSR_WRITE_4(sc, STGE_RFDListPtrLo,
- STGE_CDRXADDR(sc, sc->sc_rxptr));
+ STGE_CDRXADDR(sc, sc->sc_rx_cons));
/*
* Initialize the Tx auto-poll period. It's OK to make this number
@@ -1332,10 +1278,7 @@ stge_init(struct ifnet *ifp)
ifp->if_flags |= IFF_RUNNING;
ifp->if_flags &= ~IFF_OACTIVE;
- out:
- if (error)
- printf("%s: interface not running\n", sc->sc_dev.dv_xname);
- return (error);
+ return (0);
}
/*
@@ -1349,7 +1292,7 @@ stge_rxdrain(struct stge_softc *sc)
struct stge_descsoft *ds;
int i;
- for (i = 0; i < STGE_NRXDESC; i++) {
+ for (i = 0; i < sc->sc_rx_cnt ; i++) {
ds = &sc->sc_rxsoft[i];
if (ds->ds_mbuf != NULL) {
bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap);
@@ -1358,8 +1301,18 @@ stge_rxdrain(struct stge_softc *sc)
ds->ds_mbuf = NULL;
}
}
+ sc->sc_rx_prod = sc->sc_rx_cons = sc->sc_rx_cnt = 0;
}
+void
+stge_fill_rx_ring(struct stge_softc *sc)
+{
+ while(sc->sc_rx_cnt < STGE_NRXDESC) {
+ if(stge_add_rxbuf(sc, sc->sc_rx_prod) == ENOBUFS)
+ break;
+ }
+}
+
/*
* stge_stop: [ ifnet interface function ]
*
@@ -1420,6 +1373,7 @@ stge_stop(struct ifnet *ifp, int disable
if (disable)
stge_rxdrain(sc);
+
}
static int
@@ -1468,16 +1422,10 @@ stge_add_rxbuf(struct stge_softc *sc, in
struct mbuf *m;
int error;
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m == NULL)
+ m = MCLGETI(NULL, M_DONTWAIT, &sc->sc_arpcom.ac_if, MCLBYTES);
+ if (!m)
return (ENOBUFS);
- MCLGET(m, M_DONTWAIT);
- if ((m->m_flags & M_EXT) == 0) {
- m_freem(m);
- return (ENOBUFS);
- }
-
m->m_data = m->m_ext.ext_buf + 2;
m->m_len = MCLBYTES - 2;
@@ -1487,7 +1435,7 @@ stge_add_rxbuf(struct stge_softc *sc, in
ds->ds_mbuf = m;
error = bus_dmamap_load(sc->sc_dmat, ds->ds_dmamap,
- m->m_ext.ext_buf, m->m_ext.ext_size, NULL, BUS_DMA_NOWAIT);
+ m->m_ext.ext_buf, m->m_ext.ext_size, NULL, BUS_DMA_NOWAIT);
if (error) {
printf("%s: can't load rx DMA map %d, error = %d\n",
sc->sc_dev.dv_xname, idx, error);
@@ -1498,6 +1446,8 @@ stge_add_rxbuf(struct stge_softc *sc, in
ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
STGE_INIT_RXDESC(sc, idx);
+ sc->sc_rx_prod = STGE_NEXTRX(sc->sc_rx_prod);
+ sc->sc_rx_cnt++;
return (0);
}
Index: src/sys/dev/pci/if_stgereg.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_stgereg.h,v
retrieving revision 1.11
diff -u -p -r1.11 if_stgereg.h
--- src/sys/dev/pci/if_stgereg.h 10 Aug 2009 19:41:05 -0000 1.11
+++ src/sys/dev/pci/if_stgereg.h 12 Dec 2010 18:15:22 -0000
@@ -478,6 +478,7 @@ struct stge_rfd {
* Receive descriptor list size.
*/
#define STGE_NRXDESC 256
+#define STGE_NRXDESC_MIN 6
#define STGE_NRXDESC_MASK (STGE_NRXDESC - 1)
#define STGE_NEXTRX(x) (((x) + 1) & STGE_NRXDESC_MASK)
@@ -544,7 +545,7 @@ struct stge_softc {
*/
struct stge_descsoft sc_txsoft[STGE_NTXDESC];
struct stge_descsoft sc_rxsoft[STGE_NRXDESC];
-
+ u_int32_t sc_rx_cnt, sc_rx_prod, sc_rx_cons;
/*
* Control data structures.
*/
@@ -556,7 +557,6 @@ struct stge_softc {
int sc_txdirty; /* first dirty Tx descriptor */
int sc_txlast; /* last used Tx descriptor */
- int sc_rxptr; /* next ready Rx descriptor/descsoft */
int sc_rxdiscard;
int sc_rxlen;
struct mbuf *sc_rxhead;
@@ -610,10 +610,22 @@ do {
\
__rfd->rfd_frag.frag_word0 = \
htole64(FRAG_ADDR(__ds->ds_dmamap->dm_segs[0].ds_addr + 2) |\
FRAG_LEN(MCLBYTES - 2)); \
- __rfd->rfd_next = \
- htole64((uint64_t)STGE_CDRXADDR((sc), STGE_NEXTRX((x)))); \
__rfd->rfd_status = 0; \
STGE_CDRXSYNC((sc), (x), BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); \
+} while (/*CONSTCOND*/0)
+
+#define STGE_INIT_RING_RXDESC(sc, x) \
+do { \
+ struct stge_rfd *__rfd = &(sc)->sc_rxdescs[(x)]; \
+ \
+ if (x < STGE_NRXDESC) \
+ __rfd->rfd_next = \
+ htole64((uint64_t)STGE_CDRXADDR((sc), STGE_NEXTRX((x))));\
+ else \
+ __rfd->rfd_next = \
+ htole64((uint64_t)STGE_CDRXADDR((sc), STGE_NEXTRX((-1))));\
+ __rfd->rfd_status = 0; \
+ STGE_CDRXSYNC((sc), (x), BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); \
} while (/*CONSTCOND*/0)
#define STGE_TIMEOUT 1000