diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2008-11-26 13:30:30 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2008-11-26 13:30:30 +0000 |
commit | 9fc6506f61684753736370438d5ee8a3a2955c97 (patch) | |
tree | 4b2d00e86e8e341f974a81d0851e802dec1ea9d1 /sys | |
parent | 2e1c8cf8f7edacaa8dc01f570b841beda4912227 (diff) |
Use bus_dmamap_load_mbuf instead of loading mbuf fragments ourselves, and
use m_defrag to linearize packets that don't fit in 16 segments.
ok claudio@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/ic/hme.c | 206 | ||||
-rw-r--r-- | sys/dev/ic/hmevar.h | 4 |
2 files changed, 89 insertions, 121 deletions
diff --git a/sys/dev/ic/hme.c b/sys/dev/ic/hme.c index f80e9e04ada..ea3127d02e3 100644 --- a/sys/dev/ic/hme.c +++ b/sys/dev/ic/hme.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hme.c,v 1.51 2008/10/02 20:21:13 brad Exp $ */ +/* $OpenBSD: hme.c,v 1.52 2008/11/26 13:30:29 kettenis Exp $ */ /* $NetBSD: hme.c,v 1.21 2001/07/07 15:59:37 thorpej Exp $ */ /*- @@ -94,7 +94,6 @@ 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); -int hme_encap(struct hme_softc *, struct mbuf *, int *); /* MII methods & callbacks */ static int hme_mii_readreg(struct device *, int, int); @@ -152,7 +151,7 @@ hme_config(sc) hme_stop(sc); for (i = 0; i < HME_TX_RING_SIZE; i++) { - if (bus_dmamap_create(sc->sc_dmatag, MCLBYTES, 1, + if (bus_dmamap_create(sc->sc_dmatag, MCLBYTES, HME_TX_NSEGS, MCLBYTES, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sc->sc_txd[i].sd_map) != 0) { sc->sc_txd[i].sd_map = NULL; @@ -384,14 +383,11 @@ hme_stop(sc) printf("%s: hme_stop: reset failed\n", sc->sc_dev.dv_xname); for (n = 0; n < HME_TX_RING_SIZE; n++) { - if (sc->sc_txd[n].sd_loaded) { + if (sc->sc_txd[n].sd_mbuf != NULL) { bus_dmamap_sync(sc->sc_dmatag, sc->sc_txd[n].sd_map, 0, sc->sc_txd[n].sd_map->dm_mapsize, BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(sc->sc_dmatag, sc->sc_txd[n].sd_map); - sc->sc_txd[n].sd_loaded = 0; - } - if (sc->sc_txd[n].sd_mbuf != NULL) { m_freem(sc->sc_txd[n].sd_mbuf); sc->sc_txd[n].sd_mbuf = NULL; } @@ -629,18 +625,52 @@ hme_start(ifp) struct ifnet *ifp; { struct hme_softc *sc = (struct hme_softc *)ifp->if_softc; + struct hme_ring *hr = &sc->sc_rb; struct mbuf *m; - int bix, cnt = 0; + u_int32_t flags; + bus_dmamap_t map; + u_int32_t frag, cur, i; + int error; if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) return; - bix = sc->sc_tx_prod; - while (sc->sc_txd[bix].sd_mbuf == NULL) { + while (sc->sc_txd[sc->sc_tx_prod].sd_mbuf == NULL) { IFQ_POLL(&ifp->if_snd, m); if (m == NULL) break; + /* + * Encapsulate this packet and start it going... + * or fail... + */ + + cur = frag = sc->sc_tx_prod; + map = sc->sc_txd[cur].sd_map; + + error = bus_dmamap_load_mbuf(sc->sc_dmatag, map, m, + BUS_DMA_NOWAIT); + if (error != 0 && error != EFBIG) + goto drop; + if (error != 0) { + /* Too many fragments, linearize. */ + if (m_defrag(m, M_DONTWAIT)) + goto drop; + error = bus_dmamap_load_mbuf(sc->sc_dmatag, map, m, + BUS_DMA_NOWAIT); + if (error != 0) + goto drop; + } + + if ((HME_TX_RING_SIZE - (sc->sc_tx_cnt + map->dm_nsegs)) < 5) { + bus_dmamap_unload(sc->sc_dmatag, map); + ifp->if_flags |= IFF_OACTIVE; + break; + } + + /* We are now committed to transmitting the packet. */ + IFQ_DEQUEUE(&ifp->if_snd, m); + #if NBPFILTER > 0 /* * If BPF is listening on this interface, let it see the @@ -650,22 +680,53 @@ hme_start(ifp) bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT); #endif - if (hme_encap(sc, m, &bix)) { - ifp->if_flags |= IFF_OACTIVE; - break; + bus_dmamap_sync(sc->sc_dmatag, map, 0, map->dm_mapsize, + BUS_DMASYNC_PREWRITE); + + for (i = 0; i < map->dm_nsegs; i++) { + flags = HME_XD_ENCODE_TSIZE(map->dm_segs[i].ds_len); + if (i == 0) + flags |= HME_XD_SOP; + else + flags |= HME_XD_OWN; + + HME_XD_SETADDR(sc->sc_pci, hr->rb_txd, frag, + map->dm_segs[i].ds_addr); + HME_XD_SETFLAGS(sc->sc_pci, hr->rb_txd, frag, flags); + + cur = frag; + if (++frag == HME_TX_RING_SIZE) + frag = 0; } - IFQ_DEQUEUE(&ifp->if_snd, m); + /* Set end of packet on last descriptor. */ + flags = HME_XD_GETFLAGS(sc->sc_pci, hr->rb_txd, cur); + flags |= HME_XD_EOP; + HME_XD_SETFLAGS(sc->sc_pci, hr->rb_txd, cur, flags); + + sc->sc_tx_cnt += map->dm_nsegs; + sc->sc_txd[sc->sc_tx_prod].sd_map = sc->sc_txd[cur].sd_map; + sc->sc_txd[cur].sd_map = map; + sc->sc_txd[cur].sd_mbuf = m; + + /* Give first frame over to the hardware. */ + flags = HME_XD_GETFLAGS(sc->sc_pci, hr->rb_txd, sc->sc_tx_prod); + flags |= HME_XD_OWN; + HME_XD_SETFLAGS(sc->sc_pci, hr->rb_txd, sc->sc_tx_prod, flags); bus_space_write_4(sc->sc_bustag, sc->sc_etx, HME_ETXI_PENDING, HME_ETX_TP_DMAWAKEUP); - cnt++; - } + sc->sc_tx_prod = frag; - if (cnt != 0) { - sc->sc_tx_prod = bix; ifp->if_timer = 5; } + + return; + + drop: + IFQ_DEQUEUE(&ifp->if_snd, m); + m_free(m); + ifp->if_oerrors++; } /* @@ -697,12 +758,10 @@ hme_tint(sc) if (txflags & HME_XD_EOP) ifp->if_opackets++; - bus_dmamap_sync(sc->sc_dmatag, sd->sd_map, - 0, sd->sd_map->dm_mapsize, BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(sc->sc_dmatag, sd->sd_map); - sd->sd_loaded = 0; - if (sd->sd_mbuf != NULL) { + bus_dmamap_sync(sc->sc_dmatag, sd->sd_map, + 0, sd->sd_map->dm_mapsize, BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(sc->sc_dmatag, sd->sd_map); m_freem(sd->sd_mbuf); sd->sd_mbuf = NULL; } @@ -1385,93 +1444,6 @@ chipit: } int -hme_encap(sc, mhead, bixp) - struct hme_softc *sc; - struct mbuf *mhead; - int *bixp; -{ - struct hme_sxd *sd; - struct mbuf *m; - int frag, cur, cnt = 0; - u_int32_t flags; - struct hme_ring *hr = &sc->sc_rb; - - cur = frag = *bixp; - sd = &sc->sc_txd[frag]; - - for (m = mhead; m != NULL; m = m->m_next) { - if (m->m_len == 0) - continue; - - if ((HME_TX_RING_SIZE - (sc->sc_tx_cnt + cnt)) < 5) - goto err; - - if (bus_dmamap_load(sc->sc_dmatag, sd->sd_map, - mtod(m, caddr_t), m->m_len, NULL, BUS_DMA_NOWAIT) != 0) - goto err; - - sd->sd_loaded = 1; - bus_dmamap_sync(sc->sc_dmatag, sd->sd_map, 0, - sd->sd_map->dm_mapsize, BUS_DMASYNC_PREWRITE); - - sd->sd_mbuf = NULL; - - flags = HME_XD_ENCODE_TSIZE(m->m_len); - if (cnt == 0) - flags |= HME_XD_SOP; - else - flags |= HME_XD_OWN; - - HME_XD_SETADDR(sc->sc_pci, hr->rb_txd, frag, - sd->sd_map->dm_segs[0].ds_addr); - HME_XD_SETFLAGS(sc->sc_pci, hr->rb_txd, frag, flags); - - cur = frag; - cnt++; - if (++frag == HME_TX_RING_SIZE) { - frag = 0; - sd = sc->sc_txd; - } else - sd++; - } - - /* Set end of packet on last descriptor. */ - flags = HME_XD_GETFLAGS(sc->sc_pci, hr->rb_txd, cur); - flags |= HME_XD_EOP; - HME_XD_SETFLAGS(sc->sc_pci, hr->rb_txd, cur, flags); - sc->sc_txd[cur].sd_mbuf = mhead; - - /* Give first frame over to the hardware. */ - flags = HME_XD_GETFLAGS(sc->sc_pci, hr->rb_txd, (*bixp)); - flags |= HME_XD_OWN; - HME_XD_SETFLAGS(sc->sc_pci, hr->rb_txd, (*bixp), flags); - - sc->sc_tx_cnt += cnt; - *bixp = frag; - - /* sync descriptors */ - - return (0); - -err: - /* - * Invalidate the stuff we may have already put into place. We - * will be called again to queue it later. - */ - for (; cnt > 0; cnt--) { - if (--frag == -1) - frag = HME_TX_RING_SIZE - 1; - sd = &sc->sc_txd[frag]; - bus_dmamap_sync(sc->sc_dmatag, sd->sd_map, 0, - sd->sd_map->dm_mapsize, BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(sc->sc_dmatag, sd->sd_map); - sd->sd_loaded = 0; - sd->sd_mbuf = NULL; - } - return (ENOBUFS); -} - -int hme_newbuf(sc, d, freeit) struct hme_softc *sc; struct hme_sxd *d; @@ -1509,24 +1481,20 @@ hme_newbuf(sc, d, freeit) * in place. */ - if (d->sd_loaded) { + 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); - d->sd_loaded = 0; - } - - if ((d->sd_mbuf != NULL) && freeit) { - m_freem(d->sd_mbuf); - d->sd_mbuf = NULL; + 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; - d->sd_loaded = 1; - bus_dmamap_sync(sc->sc_dmatag, d->sd_map, 0, d->sd_map->dm_mapsize, BUS_DMASYNC_PREREAD); diff --git a/sys/dev/ic/hmevar.h b/sys/dev/ic/hmevar.h index 8588373b3ee..033024f03f1 100644 --- a/sys/dev/ic/hmevar.h +++ b/sys/dev/ic/hmevar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: hmevar.h,v 1.10 2008/06/26 05:42:15 ray Exp $ */ +/* $OpenBSD: hmevar.h,v 1.11 2008/11/26 13:30:29 kettenis Exp $ */ /* $NetBSD: hmevar.h,v 1.6 2000/09/28 10:56:57 tsutsui Exp $ */ /*- @@ -37,11 +37,11 @@ #define HME_RX_RING_MAX 256 #define HME_TX_RING_MAX 256 #define HME_RX_PKTSIZE 1600 +#define HME_TX_NSEGS 16 struct hme_sxd { struct mbuf *sd_mbuf; /* descriptor mbuf */ bus_dmamap_t sd_map; /* descriptor dmamap */ - int sd_loaded; /* descriptor dmamap loaded? */ }; struct hme_ring { |