diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2009-11-23 16:36:23 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2009-11-23 16:36:23 +0000 |
commit | 6b4ca9ab5e505da5e3e0a2bb5cbcbc76d1dd678e (patch) | |
tree | 5d2bf1e7bd273f2d33566bee4c23d7523052df41 /sys/dev/ic | |
parent | c58f71a9d88cb9ff90fce3e2d85ad187973565ec (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.c | 113 | ||||
-rw-r--r-- | sys/dev/ic/elink3var.h | 3 |
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 = ⊤ /* * 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 */ |