summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorJason Wright <jason@cvs.openbsd.org>2002-08-08 03:32:01 +0000
committerJason Wright <jason@cvs.openbsd.org>2002-08-08 03:32:01 +0000
commit2cfa566148bfb4cf272fd22a4e9cac25fbdc1a5a (patch)
tree7448e441223d8be885c053f898d17522f261c42c /sys/arch
parent0fbf6e856c6c92dac5d02bc2a4ead2a6b5d3e569 (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.c122
-rw-r--r--sys/arch/sparc/dev/bereg.h4
-rw-r--r--sys/arch/sparc/dev/bevar.h5
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;
};