summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2008-11-26 13:30:30 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2008-11-26 13:30:30 +0000
commit9fc6506f61684753736370438d5ee8a3a2955c97 (patch)
tree4b2d00e86e8e341f974a81d0851e802dec1ea9d1 /sys
parent2e1c8cf8f7edacaa8dc01f570b841beda4912227 (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.c206
-rw-r--r--sys/dev/ic/hmevar.h4
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 {