diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2009-04-17 20:20:19 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2009-04-17 20:20:19 +0000 |
commit | dca6bc7fb9113b283996a679449951191483c281 (patch) | |
tree | dee680b3813763d829cbe4b1041d3b0bd88caf2c | |
parent | edaa0ba623f3a5f791a302917d047fe6a634419c (diff) |
Switch hme(4) over to using MCLGETI when allocating mbufs for the RX ring.
tested by okan@, sthen@
-rw-r--r-- | sys/dev/ic/hme.c | 119 | ||||
-rw-r--r-- | sys/dev/ic/hmevar.h | 4 |
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; }; |