diff options
author | Jason Wright <jason@cvs.openbsd.org> | 2002-08-08 03:32:01 +0000 |
---|---|---|
committer | Jason Wright <jason@cvs.openbsd.org> | 2002-08-08 03:32:01 +0000 |
commit | 2cfa566148bfb4cf272fd22a4e9cac25fbdc1a5a (patch) | |
tree | 7448e441223d8be885c053f898d17522f261c42c /sys/arch | |
parent | 0fbf6e856c6c92dac5d02bc2a4ead2a6b5d3e569 (diff) |
Completely rework transmit interrupt handling:
- try to handle tx ring reclaim in bestart()
- if we pass over the high water mark, enable TX interrupts
- disable them again when the low water mark is passed
Thanks to mickey@ for enduring 4 versions of this =)
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/sparc/dev/be.c | 122 | ||||
-rw-r--r-- | sys/arch/sparc/dev/bereg.h | 4 | ||||
-rw-r--r-- | sys/arch/sparc/dev/bevar.h | 5 |
3 files changed, 95 insertions, 36 deletions
diff --git a/sys/arch/sparc/dev/be.c b/sys/arch/sparc/dev/be.c index fb1641b3081..f1f766681df 100644 --- a/sys/arch/sparc/dev/be.c +++ b/sys/arch/sparc/dev/be.c @@ -1,4 +1,4 @@ -/* $OpenBSD: be.c,v 1.32 2002/04/30 01:12:28 art Exp $ */ +/* $OpenBSD: be.c,v 1.33 2002/08/08 03:32:00 jason Exp $ */ /* * Copyright (c) 1998 Theo de Raadt and Jason L. Wright. @@ -37,6 +37,7 @@ #include <sys/syslog.h> #include <sys/device.h> #include <sys/malloc.h> +#include <sys/timeout.h> #include <net/if.h> #include <net/if_dl.h> @@ -97,6 +98,8 @@ int be_tcvr_read(struct besoftc *, u_int8_t); void be_ifmedia_sts(struct ifnet *, struct ifmediareq *); int be_ifmedia_upd(struct ifnet *); void be_mcreset(struct besoftc *); +void betick(void *); +void be_tx_harvest(struct besoftc *); struct cfdriver be_cd = { NULL, "be", DV_IFNET @@ -140,6 +143,8 @@ beattach(parent, self, aux) pri = ca->ca_ra.ra_intr[0].int_pri; sc->sc_rev = getpropint(ca->ca_ra.ra_node, "board-version", -1); + timeout_set(&sc->sc_tick, betick, sc); + sc->sc_cr = mapiodev(&ca->ca_ra.ra_reg[0], 0, sizeof(struct be_cregs)); sc->sc_br = mapiodev(&ca->ca_ra.ra_reg[1], 0, sizeof(struct be_bregs)); sc->sc_tr = mapiodev(&ca->ca_ra.ra_reg[2], 0, sizeof(struct be_tregs)); @@ -250,12 +255,18 @@ bestart(ifp) { struct besoftc *sc = (struct besoftc *)ifp->if_softc; struct mbuf *m; - int bix, len; + int bix, len, cnt; + + if (sc->sc_no_td > 0) { + /* Try to free previous stuff */ + be_tx_harvest(sc); + } if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) return; bix = sc->sc_last_td; + cnt = sc->sc_no_td; for (;;) { IFQ_POLL(&ifp->if_snd, m); @@ -289,13 +300,23 @@ bestart(ifp) if (++bix == BE_TX_RING_MAXSIZE) bix = 0; - if (++sc->sc_no_td == BE_TX_RING_SIZE) { + if (++cnt == BE_TX_RING_SIZE) { ifp->if_flags |= IFF_OACTIVE; break; } } - sc->sc_last_td = bix; + if (cnt > BE_TX_HIGH_WATER) { + /* turn on interrupt */ + sc->sc_tx_intr = 1; + sc->sc_cr->timask = 0; + } + + if (cnt != sc->sc_no_td) { + ifp->if_timer = 5; + sc->sc_last_td = bix; + sc->sc_no_td = cnt; + } } void @@ -304,6 +325,10 @@ bestop(sc) { int tries; + sc->sc_arpcom.ac_if.if_timer = 0; + if (timeout_pending(&sc->sc_tick)) + timeout_del(&sc->sc_tick); + tries = 32; sc->sc_br->tx_cfg = 0; while (sc->sc_br->tx_cfg != 0 && --tries) @@ -360,7 +385,7 @@ beintr(v) if (whyq & QEC_STAT_ER) r |= beqint(sc, whyc); - if (whyq & QEC_STAT_TX && whyc & BE_CR_STAT_TXIRQ) + if (sc->sc_tx_intr && (whyq & QEC_STAT_TX) && (whyc & BE_CR_STAT_TXIRQ)) r |= betint(sc); if (whyq & QEC_STAT_RX && whyc & BE_CR_STAT_RXIRQ) @@ -424,31 +449,19 @@ beeint(sc, why) return r; } -/* - * Transmit interrupt. - */ -int -betint(sc) +void +be_tx_harvest(sc) struct besoftc *sc; { struct ifnet *ifp = &sc->sc_arpcom.ac_if; - struct be_bregs *br = sc->sc_br; - int bix; + int bix, cnt; struct be_txd txd; - /* - * Get collision counters - */ - ifp->if_collisions += br->nc_ctr + br->fc_ctr + br->ex_ctr + br->lt_ctr; - br->nc_ctr = 0; - br->fc_ctr = 0; - br->ex_ctr = 0; - br->lt_ctr = 0; - bix = sc->sc_first_td; + cnt = sc->sc_no_td; for (;;) { - if (sc->sc_no_td <= 0) + if (cnt <= 0) break; txd.tx_flags = sc->sc_desc->be_txd[bix].tx_flags; @@ -461,24 +474,35 @@ betint(sc) if (++bix == BE_TX_RING_MAXSIZE) bix = 0; - --sc->sc_no_td; + --cnt; } - if (sc->sc_no_td == 0) + if (cnt <= 0) ifp->if_timer = 0; - /* - * If we freed up at least one descriptor and tx is blocked, - * unblock it and start it up again. - */ - if (sc->sc_first_td != bix) { + if (sc->sc_no_td != cnt) { sc->sc_first_td = bix; - if (ifp->if_flags & IFF_OACTIVE) { - ifp->if_flags &= ~IFF_OACTIVE; - bestart(ifp); - } + sc->sc_no_td = cnt; + ifp->if_flags &= ~IFF_OACTIVE; } + if (sc->sc_no_td < BE_TX_LOW_WATER) { + /* turn off interrupt */ + sc->sc_tx_intr = 0; + sc->sc_cr->timask = 0xffffffff; + } +} + +/* + * Transmit interrupt. + */ +int +betint(sc) + struct besoftc *sc; +{ + struct ifnet *ifp = &sc->sc_arpcom.ac_if; + + bestart(ifp); return (1); } @@ -515,6 +539,29 @@ berint(sc) return 1; } +void +betick(vsc) + void *vsc; +{ + struct besoftc *sc = vsc; + struct ifnet *ifp = &sc->sc_arpcom.ac_if; + struct be_bregs *br = sc->sc_br; + int s; + + s = splnet(); + /* + * Get collision counters + */ + ifp->if_collisions += br->nc_ctr + br->fc_ctr + br->ex_ctr + br->lt_ctr; + br->nc_ctr = 0; + br->fc_ctr = 0; + br->ex_ctr = 0; + br->lt_ctr = 0; + bestart(ifp); + splx(s); + timeout_add(&sc->sc_tick, hz); +} + int beioctl(ifp, cmd, data) struct ifnet *ifp; @@ -706,7 +753,11 @@ beinit(sc) BE_BR_IMASK_DTIMEXP; cr->rimask = 0; - cr->timask = 0; + + /* disable tx interrupts initially */ + cr->timask = 0xffffffff; + sc->sc_tx_intr = 0; + cr->qmask = 0; cr->bmask = 0; @@ -720,6 +771,9 @@ beinit(sc) ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; splx(s); + + timeout_add(&sc->sc_tick, hz); + bestart(ifp); } /* diff --git a/sys/arch/sparc/dev/bereg.h b/sys/arch/sparc/dev/bereg.h index 7eb3bed45da..388ca36bf90 100644 --- a/sys/arch/sparc/dev/bereg.h +++ b/sys/arch/sparc/dev/bereg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bereg.h,v 1.10 2002/06/03 20:01:36 deraadt Exp $ */ +/* $OpenBSD: bereg.h,v 1.11 2002/08/08 03:32:00 jason Exp $ */ /* * Copyright (c) 1998 Theo de Raadt and Jason L. Wright. @@ -260,6 +260,8 @@ struct be_txd { #define BE_TX_RING_SIZE 32 /* power of 2, <= MAXSIZE */ #define BE_RX_RING_SIZE 32 /* power of 2, <= MAXSIZE */ #define BE_PKT_BUF_SZ 2048 +#define BE_TX_HIGH_WATER 27 /* enable tx interrupt */ +#define BE_TX_LOW_WATER 5 /* disable tx interrupt */ #define BE_TX_RING_MAXMASK (BE_TX_RING_MAXSIZE-1) #define BE_RX_RING_MAXMASK (BE_RX_RING_MAXSIZE-1) diff --git a/sys/arch/sparc/dev/bevar.h b/sys/arch/sparc/dev/bevar.h index cddde57010f..87e8e1d6835 100644 --- a/sys/arch/sparc/dev/bevar.h +++ b/sys/arch/sparc/dev/bevar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bevar.h,v 1.11 2001/11/27 02:47:49 jason Exp $ */ +/* $OpenBSD: bevar.h,v 1.12 2002/08/08 03:32:00 jason Exp $ */ /* * Copyright (c) 1998 Theo de Raadt and Jason L. Wright. @@ -45,10 +45,13 @@ struct besoftc { int sc_channel; /* channel number */ int sc_burst; int sc_tcvr_type; + int sc_tx_intr; struct be_bufs *sc_bufs, *sc_bufs_dva; struct be_desc *sc_desc, *sc_desc_dva; int sc_no_td, sc_first_td, sc_last_td; int sc_last_rd; + + struct timeout sc_tick; }; |