Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/ic Make sure to allocate big enough mbuf data area b...
details: https://anonhg.NetBSD.org/src/rev/6e9990ce72c3
branches: trunk
changeset: 510004:6e9990ce72c3
user: jdolecek <jdolecek%NetBSD.org@localhost>
date: Wed May 16 20:30:52 2001 +0000
description:
Make sure to allocate big enough mbuf data area before elevating
interrupt priority, to avoid allocating additional mbufs on
splsched(). Move some other misc bits out of splched()-guarded
section. This should make the code a bit more friendly wrt e.g.
clock interrupts. Sligh performance improvement was observed with
this change (like 1-2% on slow machine), even.
This also fixes ancient kern/2478 by Bill Sommerfeld.
diffstat:
sys/dev/ic/elink3.c | 166 +++++++++++++++++++++++----------------------------
1 files changed, 75 insertions(+), 91 deletions(-)
diffs (223 lines):
diff -r 44676c52142e -r 6e9990ce72c3 sys/dev/ic/elink3.c
--- a/sys/dev/ic/elink3.c Wed May 16 19:06:46 2001 +0000
+++ b/sys/dev/ic/elink3.c Wed May 16 20:30:52 2001 +0000
@@ -1,7 +1,7 @@
-/* $NetBSD: elink3.c,v 1.92 2001/05/14 09:28:49 jdolecek Exp $ */
+/* $NetBSD: elink3.c,v 1.93 2001/05/16 20:30:52 jdolecek Exp $ */
/*-
- * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -1592,10 +1592,12 @@
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
- struct mbuf *top, **mp, *m, *rv = NULL;
+ struct mbuf *m;
bus_addr_t rxreg;
int len, remaining;
- int sh;
+ int s;
+ caddr_t newdata;
+ u_long offset;
m = sc->mb[sc->next_mb];
sc->mb[sc->next_mb] = 0;
@@ -1607,6 +1609,7 @@
/* If the queue is no longer full, refill. */
if (sc->last_mb == sc->next_mb)
callout_reset(&sc->sc_mbuf_callout, 1, epmbuffill, sc);
+
/* Convert one of our saved mbuf's. */
sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
m->m_data = m->m_pktdat;
@@ -1616,8 +1619,34 @@
m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = totlen;
len = MHLEN;
- top = 0;
- mp = ⊤
+
+ /*
+ * Allocate big enough space to hold whole packet, to avoid
+ * allocating new mbufs on splsched().
+ */
+ if (totlen + ALIGNBYTES > len) {
+ if (totlen + ALIGNBYTES > MCLBYTES) {
+ len = ALIGN(totlen + ALIGNBYTES);
+ MEXTMALLOC(m, len, M_DONTWAIT);
+ } else {
+ len = MCLBYTES;
+ MCLGET(m, M_DONTWAIT);
+ }
+ if ((m->m_flags & M_EXT) == 0) {
+ m_free(m);
+ return 0;
+ }
+ }
+
+ /* align the struct ip header */
+ newdata = (caddr_t) ALIGN(m->m_data + sizeof(struct ether_header))
+ - sizeof(struct ether_header);
+ m->m_data = newdata;
+ m->m_len = totlen;
+
+ rxreg = ep_w1_reg(sc, ELINK_W1_RX_PIO_RD_1);
+ remaining = totlen;
+ offset = mtod(m, u_long);
/*
* We read the packet at a high interrupt priority level so that
@@ -1629,9 +1658,7 @@
*
* XXX THIS CAN CAUSE CLOCK DRIFT!
*/
- sh = splsched();
-
- rxreg = ep_w1_reg(sc, ELINK_W1_RX_PIO_RD_1);
+ s = splsched();
if (sc->ep_flags & ELINK_FLAGS_USEFIFOBUFFER) {
/*
@@ -1644,99 +1671,56 @@
bus_space_write_2(iot, ioh, ELINK_W1_RUNNER_RDCTL, totlen >> 1);
}
- while (totlen > 0) {
- if (top) {
- m = sc->mb[sc->next_mb];
- sc->mb[sc->next_mb] = 0;
- if (m == 0) {
- MGET(m, M_DONTWAIT, MT_DATA);
- if (m == 0) {
- m_freem(top);
- goto out;
- }
- } else {
- sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
- }
- len = MLEN;
+ if (ELINK_IS_BUS_32(sc->bustype)) {
+ /*
+ * Read bytes up to the point where we are aligned.
+ * (We can align to 4 bytes, rather than ALIGNBYTES,
+ * here because we're later reading 4-byte chunks.)
+ */
+ if ((remaining > 3) && (offset & 3)) {
+ int count = (4 - (offset & 3));
+ bus_space_read_multi_1(iot, ioh,
+ rxreg, (u_int8_t *) offset, count);
+ offset += count;
+ remaining -= count;
}
- if (totlen >= MINCLSIZE) {
- MCLGET(m, M_DONTWAIT);
- if ((m->m_flags & M_EXT) == 0) {
- m_free(m);
- m_freem(top);
- goto out;
- }
- len = MCLBYTES;
- }
- if (top == 0) {
- /* align the struct ip header */
- caddr_t newdata = (caddr_t)
- ALIGN(m->m_data + sizeof(struct ether_header))
- - sizeof(struct ether_header);
- len -= newdata - m->m_data;
- m->m_data = newdata;
+ if (remaining > 3) {
+ bus_space_read_multi_stream_4(iot, ioh,
+ rxreg, (u_int32_t *) offset,
+ remaining >> 2);
+ offset += remaining & ~3;
+ remaining &= 3;
}
- remaining = len = min(totlen, len);
- if (ELINK_IS_BUS_32(sc->bustype)) {
- u_long offset = mtod(m, u_long);
- /*
- * Read bytes up to the point where we are aligned.
- * (We can align to 4 bytes, rather than ALIGNBYTES,
- * here because we're later reading 4-byte chunks.)
- */
- if ((remaining > 3) && (offset & 3)) {
- int count = (4 - (offset & 3));
- bus_space_read_multi_1(iot, ioh,
- rxreg, (u_int8_t *) offset, count);
- offset += count;
- remaining -= count;
- }
- if (remaining > 3) {
- bus_space_read_multi_stream_4(iot, ioh,
- rxreg, (u_int32_t *) offset,
- remaining >> 2);
- offset += remaining & ~3;
- remaining &= 3;
- }
- if (remaining) {
+ if (remaining) {
+ bus_space_read_multi_1(iot, ioh,
+ rxreg, (u_int8_t *) offset, remaining);
+ }
+ } else {
+ if ((remaining > 1) && (offset & 1)) {
+ bus_space_read_multi_1(iot, ioh,
+ rxreg, (u_int8_t *) offset, 1);
+ remaining -= 1;
+ offset += 1;
+ }
+ if (remaining > 1) {
+ bus_space_read_multi_stream_2(iot, ioh,
+ rxreg, (u_int16_t *) offset,
+ remaining >> 1);
+ offset += remaining & ~1;
+ }
+ if (remaining & 1) {
bus_space_read_multi_1(iot, ioh,
- rxreg, (u_int8_t *) offset, remaining);
- }
- } else {
- u_long offset = mtod(m, u_long);
- if ((remaining > 1) && (offset & 1)) {
- bus_space_read_multi_1(iot, ioh,
- rxreg, (u_int8_t *) offset, 1);
- remaining -= 1;
- offset += 1;
- }
- if (remaining > 1) {
- bus_space_read_multi_stream_2(iot, ioh,
- rxreg, (u_int16_t *) offset,
- remaining >> 1);
- offset += remaining & ~1;
- }
- if (remaining & 1) {
- bus_space_read_multi_1(iot, ioh,
- rxreg, (u_int8_t *) offset, remaining & 1);
- }
+ rxreg, (u_int8_t *) offset, remaining & 1);
}
- m->m_len = len;
- totlen -= len;
- *mp = m;
- mp = &m->m_next;
}
- rv = top;
-
ep_discard_rxtop(iot, ioh);
- out:
if (sc->ep_flags & ELINK_FLAGS_USEFIFOBUFFER)
bus_space_write_2(iot, ioh, ELINK_W1_RUNNER_RDCTL, 0);
- splx(sh);
+ splx(s);
- return rv;
+ return (m);
}
int
Home |
Main Index |
Thread Index |
Old Index