summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2009-04-17 20:20:19 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2009-04-17 20:20:19 +0000
commitdca6bc7fb9113b283996a679449951191483c281 (patch)
treedee680b3813763d829cbe4b1041d3b0bd88caf2c /sys/dev
parentedaa0ba623f3a5f791a302917d047fe6a634419c (diff)
Switch hme(4) over to using MCLGETI when allocating mbufs for the RX ring.
tested by okan@, sthen@
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/hme.c119
-rw-r--r--sys/dev/ic/hmevar.h4
2 files changed, 69 insertions, 54 deletions
diff --git a/sys/dev/ic/hme.c b/sys/dev/ic/hme.c
index d6d3ea67081..26454224776 100644
--- a/sys/dev/ic/hme.c
+++ b/sys/dev/ic/hme.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hme.c,v 1.54 2008/12/10 20:37:48 brad Exp $ */
+/* $OpenBSD: hme.c,v 1.55 2009/04/17 20:20:18 kettenis Exp $ */
/* $NetBSD: hme.c,v 1.21 2001/07/07 15:59:37 thorpej Exp $ */
/*-
@@ -93,7 +93,8 @@ void hme_meminit(struct hme_softc *);
void hme_mifinit(struct hme_softc *);
void hme_reset(struct hme_softc *);
void hme_setladrf(struct hme_softc *);
-int hme_newbuf(struct hme_softc *, struct hme_sxd *, int);
+void hme_fill_rx_ring(struct hme_softc *);
+int hme_newbuf(struct hme_softc *, struct hme_sxd *);
/* MII methods & callbacks */
static int hme_mii_readreg(struct device *, int, int);
@@ -232,6 +233,8 @@ hme_config(sc)
IFQ_SET_READY(&ifp->if_snd);
ifp->if_capabilities = IFCAP_VLAN_MTU;
+ m_clsetwms(ifp, MCLBYTES, 0, HME_RX_RING_SIZE);
+
/* Initialize ifmedia structures and MII info */
mii->mii_ifp = ifp;
mii->mii_readreg = hme_mii_readreg;
@@ -392,6 +395,19 @@ hme_stop(sc)
sc->sc_txd[n].sd_mbuf = NULL;
}
}
+ sc->sc_tx_prod = sc->sc_tx_cons = sc->sc_tx_cnt = 0;
+
+ for (n = 0; n < HME_RX_RING_SIZE; n++) {
+ if (sc->sc_rxd[n].sd_mbuf != NULL) {
+ bus_dmamap_sync(sc->sc_dmatag, sc->sc_rxd[n].sd_map,
+ 0, sc->sc_rxd[n].sd_map->dm_mapsize,
+ BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->sc_dmatag, sc->sc_rxd[n].sd_map);
+ m_freem(sc->sc_rxd[n].sd_mbuf);
+ sc->sc_rxd[n].sd_mbuf = NULL;
+ }
+ }
+ sc->sc_rx_prod = sc->sc_rx_cons = sc->sc_rx_cnt = 0;
}
void
@@ -441,19 +457,12 @@ hme_meminit(sc)
* Initialize receive descriptors
*/
for (i = 0; i < HME_RX_RING_SIZE; i++) {
- if (hme_newbuf(sc, &sc->sc_rxd[i], 1)) {
- printf("%s: rx allocation failed\n",
- sc->sc_dev.dv_xname);
- break;
- }
- HME_XD_SETADDR(sc->sc_pci, hr->rb_rxd, i,
- sc->sc_rxd[i].sd_map->dm_segs[0].ds_addr);
- HME_XD_SETFLAGS(sc->sc_pci, hr->rb_rxd, i,
- HME_XD_OWN | HME_XD_ENCODE_RSIZE(HME_RX_PKTSIZE));
+ HME_XD_SETADDR(sc->sc_pci, hr->rb_rxd, i, 0);
+ HME_XD_SETFLAGS(sc->sc_pci, hr->rb_rxd, i, 0);
+ sc->sc_rxd[i].sd_mbuf = NULL;
}
- sc->sc_tx_prod = sc->sc_tx_cons = sc->sc_tx_cnt = 0;
- sc->sc_last_rd = 0;
+ hme_fill_rx_ring(sc);
}
/*
@@ -894,36 +903,42 @@ hme_rint(sc)
unsigned int ri, len;
u_int32_t flags;
- ri = sc->sc_last_rd;
+ ri = sc->sc_rx_cons;
sd = &sc->sc_rxd[ri];
/*
* Process all buffers with valid data.
*/
- for (;;) {
+ while (sc->sc_rx_cnt > 0) {
flags = HME_XD_GETFLAGS(sc->sc_pci, sc->sc_rb.rb_rxd, ri);
if (flags & HME_XD_OWN)
break;
+ bus_dmamap_sync(sc->sc_dmatag, sd->sd_map,
+ 0, sd->sd_map->dm_mapsize, BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->sc_dmatag, sd->sd_map);
+
+ m = sd->sd_mbuf;
+ sd->sd_mbuf = NULL;
+
+ if (++ri == HME_RX_RING_SIZE) {
+ ri = 0;
+ sd = sc->sc_rxd;
+ } else
+ sd++;
+ sc->sc_rx_cnt--;
+
if (flags & HME_XD_OFL) {
+ ifp->if_ierrors++;
printf("%s: buffer overflow, ri=%d; flags=0x%x\n",
sc->sc_dev.dv_xname, ri, flags);
- goto again;
+ m_freem(m);
+ continue;
}
- m = sd->sd_mbuf;
len = HME_XD_DECODE_RSIZE(flags);
m->m_pkthdr.len = m->m_len = len;
- if (hme_newbuf(sc, sd, 0)) {
- /*
- * Allocation of new mbuf cluster failed, leave the
- * old one in place and keep going.
- */
- ifp->if_ierrors++;
- goto again;
- }
-
ifp->if_ipackets++;
hme_rxcksum(m, flags);
@@ -933,21 +948,10 @@ hme_rint(sc)
#endif
ether_input_mbuf(ifp, m);
-
-again:
- HME_XD_SETADDR(sc->sc_pci, sc->sc_rb.rb_rxd, ri,
- sd->sd_map->dm_segs[0].ds_addr);
- HME_XD_SETFLAGS(sc->sc_pci, sc->sc_rb.rb_rxd, ri,
- HME_XD_OWN | HME_XD_ENCODE_RSIZE(HME_RX_PKTSIZE));
-
- if (++ri == HME_RX_RING_SIZE) {
- ri = 0;
- sd = sc->sc_rxd;
- } else
- sd++;
}
- sc->sc_last_rd = ri;
+ sc->sc_rx_cons = ri;
+ hme_fill_rx_ring(sc);
return (1);
}
@@ -1432,11 +1436,32 @@ chipit:
bus_space_write_4(t, mac, HME_MACI_RXCFG, v);
}
+void
+hme_fill_rx_ring(sc)
+ struct hme_softc *sc;
+{
+ struct hme_sxd *sd;
+
+ while (sc->sc_rx_cnt < HME_RX_RING_SIZE) {
+ if (hme_newbuf(sc, &sc->sc_rxd[sc->sc_rx_prod]))
+ break;
+
+ sd = &sc->sc_rxd[sc->sc_rx_prod];
+ HME_XD_SETADDR(sc->sc_pci, sc->sc_rb.rb_rxd, sc->sc_rx_prod,
+ sd->sd_map->dm_segs[0].ds_addr);
+ HME_XD_SETFLAGS(sc->sc_pci, sc->sc_rb.rb_rxd, sc->sc_rx_prod,
+ HME_XD_OWN | HME_XD_ENCODE_RSIZE(HME_RX_PKTSIZE));
+
+ if (++sc->sc_rx_prod == HME_RX_RING_SIZE)
+ sc->sc_rx_prod = 0;
+ sc->sc_rx_cnt++;
+ }
+}
+
int
-hme_newbuf(sc, d, freeit)
+hme_newbuf(sc, d)
struct hme_softc *sc;
struct hme_sxd *d;
- int freeit;
{
struct mbuf *m;
bus_dmamap_t map;
@@ -1451,7 +1476,7 @@ hme_newbuf(sc, d, freeit)
return (ENOBUFS);
m->m_pkthdr.rcvif = &sc->sc_arpcom.ac_if;
- MCLGET(m, M_DONTWAIT);
+ MCLGETI(m, M_DONTWAIT, &sc->sc_arpcom.ac_if, MCLBYTES);
if ((m->m_flags & M_EXT) == 0) {
m_freem(m);
return (ENOBUFS);
@@ -1470,16 +1495,6 @@ hme_newbuf(sc, d, freeit)
* in place.
*/
- if (d->sd_mbuf != NULL) {
- bus_dmamap_sync(sc->sc_dmatag, d->sd_map,
- 0, d->sd_map->dm_mapsize, BUS_DMASYNC_POSTREAD);
- bus_dmamap_unload(sc->sc_dmatag, d->sd_map);
- if (freeit) {
- m_freem(d->sd_mbuf);
- d->sd_mbuf = NULL;
- }
- }
-
map = d->sd_map;
d->sd_map = sc->sc_rxmap_spare;
sc->sc_rxmap_spare = map;
diff --git a/sys/dev/ic/hmevar.h b/sys/dev/ic/hmevar.h
index 033024f03f1..c5506600278 100644
--- a/sys/dev/ic/hmevar.h
+++ b/sys/dev/ic/hmevar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: hmevar.h,v 1.11 2008/11/26 13:30:29 kettenis Exp $ */
+/* $OpenBSD: hmevar.h,v 1.12 2009/04/17 20:20:18 kettenis Exp $ */
/* $NetBSD: hmevar.h,v 1.6 2000/09/28 10:56:57 tsutsui Exp $ */
/*-
@@ -89,7 +89,7 @@ struct hme_softc {
struct hme_sxd sc_txd[HME_TX_RING_MAX], sc_rxd[HME_RX_RING_MAX];
bus_dmamap_t sc_rxmap_spare;
int sc_tx_cnt, sc_tx_prod, sc_tx_cons;
- int sc_last_rd;
+ int sc_rx_cnt, sc_rx_prod, sc_rx_cons;
u_int32_t sc_tcvr;
};