summaryrefslogtreecommitdiff
path: root/sys/dev/ic
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2009-11-23 16:36:23 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2009-11-23 16:36:23 +0000
commit6b4ca9ab5e505da5e3e0a2bb5cbcbc76d1dd678e (patch)
tree5d2bf1e7bd273f2d33566bee4c23d7523052df41 /sys/dev/ic
parentc58f71a9d88cb9ff90fce3e2d85ad187973565ec (diff)
Bring elink3 at least a bit into the new world. It used to have some super
scary mbuf chache that caused massive problems. Now we just pre-allocate empty mbuf cluster for later use. Diff mostly from deraadt@ with some minor changes by myself. Tested with pcmcia ep(4) by myself. OK deraadt@
Diffstat (limited to 'sys/dev/ic')
-rw-r--r--sys/dev/ic/elink3.c113
-rw-r--r--sys/dev/ic/elink3var.h3
2 files changed, 41 insertions, 75 deletions
diff --git a/sys/dev/ic/elink3.c b/sys/dev/ic/elink3.c
index 59871ccb468..23692a5d15e 100644
--- a/sys/dev/ic/elink3.c
+++ b/sys/dev/ic/elink3.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: elink3.c,v 1.74 2009/11/16 13:41:49 jsg Exp $ */
+/* $OpenBSD: elink3.c,v 1.75 2009/11/23 16:36:22 claudio Exp $ */
/* $NetBSD: elink3.c,v 1.32 1997/05/14 00:22:00 thorpej Exp $ */
/*
@@ -1372,36 +1372,30 @@ epget(sc, totlen)
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
- struct mbuf *top, **mp, *m;
+ struct mbuf *m;
int len, pad, sh, rxreg;
+ splassert(IPL_NET);
+
m = sc->mb[sc->next_mb];
sc->mb[sc->next_mb] = NULL;
if (m == NULL) {
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m == NULL)
- return (NULL);
- } else {
+ m = MCLGETI(NULL, M_DONTWAIT, NULL, MCLBYTES);
/* If the queue is no longer full, refill. */
- if (sc->last_mb == sc->next_mb)
+ if (!timeout_pending(&sc->sc_epmbuffill_tmo))
timeout_add(&sc->sc_epmbuffill_tmo, 1);
- /* Convert one of our saved mbuf's. */
- sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
- m = m_inithdr(m);
}
+ if (!m)
+ return (NULL);
+
+ sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
+
+ len = MCLBYTES;
m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = totlen;
pad = ALIGN(sizeof(struct ether_header)) - sizeof(struct ether_header);
- len = MHLEN;
- if (totlen >= MINCLSIZE) {
- MCLGET(m, M_DONTWAIT);
- if (m->m_flags & M_EXT)
- len = MCLBYTES;
- }
m->m_data += pad;
len -= pad;
- top = 0;
- mp = &top;
/*
* We read the packet at splhigh() so that an interrupt from another
@@ -1412,56 +1406,31 @@ epget(sc, totlen)
rxreg = ep_w1_reg(sc, EP_W1_RX_PIO_RD_1);
- while (totlen > 0) {
- if (top) {
- m = sc->mb[sc->next_mb];
- sc->mb[sc->next_mb] = NULL;
- if (m == NULL) {
- MGET(m, M_DONTWAIT, MT_DATA);
- if (m == NULL) {
- splx(sh);
- m_freem(top);
- return (NULL);
- }
- } else
- sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
-
- len = MLEN;
- }
- if (top && totlen >= MINCLSIZE) {
- MCLGET(m, M_DONTWAIT);
- if (m->m_flags & M_EXT)
- len = MCLBYTES;
- }
- len = min(totlen, len);
- if (EP_IS_BUS_32(sc->bustype)) {
- if (len > 3) {
- len &= ~3;
- bus_space_read_raw_multi_4(iot, ioh, rxreg,
- mtod(m, u_int8_t *), len);
- } else
- bus_space_read_multi_1(iot, ioh, rxreg,
- mtod(m, u_int8_t *), len);
- } else {
- if (len > 1) {
- len &= ~1;
- bus_space_read_raw_multi_2(iot, ioh, rxreg,
- mtod(m, u_int8_t *), len);
- } else
- *(mtod(m, u_int8_t *)) =
- bus_space_read_1(iot, ioh, rxreg);
- }
- m->m_len = len;
- totlen -= len;
- *mp = m;
- mp = &m->m_next;
+ len = min(totlen, len);
+ if (EP_IS_BUS_32(sc->bustype)) {
+ if (len > 3) {
+ len &= ~3;
+ bus_space_read_raw_multi_4(iot, ioh, rxreg,
+ mtod(m, u_int8_t *), len);
+ } else
+ bus_space_read_multi_1(iot, ioh, rxreg,
+ mtod(m, u_int8_t *), len);
+ } else {
+ if (len > 1) {
+ len &= ~1;
+ bus_space_read_raw_multi_2(iot, ioh, rxreg,
+ mtod(m, u_int8_t *), len);
+ } else
+ *(mtod(m, u_int8_t *)) =
+ bus_space_read_1(iot, ioh, rxreg);
}
+ m->m_len = len;
ep_discard_rxtop(iot, ioh);
splx(sh);
- return top;
+ return m;
}
int
@@ -1693,17 +1662,15 @@ epmbuffill(v)
int s, i;
s = splnet();
- i = sc->last_mb;
- do {
- if (sc->mb[i] == NULL)
- MGET(sc->mb[i], M_DONTWAIT, MT_DATA);
- if (sc->mb[i] == NULL)
- break;
- i = (i + 1) % MAX_MBS;
- } while (i != sc->next_mb);
- sc->last_mb = i;
+ for (i = 0; i < MAX_MBS; i++) {
+ if (sc->mb[i] == NULL) {
+ sc->mb[i] = MCLGETI(NULL, M_DONTWAIT, NULL, MCLBYTES);
+ if (sc->mb[i] == NULL)
+ break;
+ }
+ }
/* If the queue was not filled, try again. */
- if (sc->last_mb != sc->next_mb)
+ if (i < MAX_MBS)
timeout_add(&sc->sc_epmbuffill_tmo, 1);
splx(s);
}
@@ -1721,7 +1688,7 @@ epmbufempty(sc)
sc->mb[i] = NULL;
}
}
- sc->last_mb = sc->next_mb = 0;
+ sc->next_mb = 0;
timeout_del(&sc->sc_epmbuffill_tmo);
splx(s);
}
diff --git a/sys/dev/ic/elink3var.h b/sys/dev/ic/elink3var.h
index 9b0262f65c9..0804c6c8783 100644
--- a/sys/dev/ic/elink3var.h
+++ b/sys/dev/ic/elink3var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: elink3var.h,v 1.18 2002/06/09 03:14:18 todd Exp $ */
+/* $OpenBSD: elink3var.h,v 1.19 2009/11/23 16:36:22 claudio Exp $ */
/* $NetBSD: elink3var.h,v 1.12 1997/03/30 22:47:11 jonathan Exp $ */
/*
@@ -47,7 +47,6 @@ struct ep_softc {
#define MAX_MBS 8 /* # of mbufs we keep around */
struct mbuf *mb[MAX_MBS]; /* spare mbuf storage. */
int next_mb; /* Which mbuf to use next. */
- int last_mb; /* Last mbuf. */
int tx_start_thresh; /* Current TX_start_thresh. */
int tx_succ_ok; /* # packets sent in sequence */
/* w/o underrun */