summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authormatt <matt@NetBSD.org>2007-04-26 23:08:22 +0000
committermatt <matt@NetBSD.org>2007-04-26 23:08:22 +0000
commite7fb6f9eb57cc1d6ece932c230000ddf4599c249 (patch)
tree14c0aedfac37ee5b204e1d1fe7b10f63a0252b94 /sys/dev
parentd4e50471e903946cfdc0a1897287980f225bb4f9 (diff)
Count tx/rx intrs.
Don't set OW in the first transmit descriptor until all descriptors have been set up. Always try to drain the transmit ring.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/sgec.c76
-rw-r--r--sys/dev/ic/sgecvar.h8
2 files changed, 63 insertions, 21 deletions
diff --git a/sys/dev/ic/sgec.c b/sys/dev/ic/sgec.c
index 88ecda0182c..ef968ddb35d 100644
--- a/sys/dev/ic/sgec.c
+++ b/sys/dev/ic/sgec.c
@@ -1,4 +1,4 @@
-/* $NetBSD: sgec.c,v 1.29 2007/04/13 04:16:45 matt Exp $ */
+/* $NetBSD: sgec.c,v 1.30 2007/04/26 23:08:22 matt Exp $ */
/*
* Copyright (c) 1999 Ludd, University of Lule}, Sweden. All rights reserved.
*
@@ -45,7 +45,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sgec.c,v 1.29 2007/04/13 04:16:45 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sgec.c,v 1.30 2007/04/26 23:08:22 matt Exp $");
#include "opt_inet.h"
#include "bpfilter.h"
@@ -182,7 +182,17 @@ sgec_attach(sc)
/* For vmstat -i
*/
evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, NULL,
- sc->sc_dev.dv_xname, "intr");
+ sc->sc_dev.dv_xname, "intr");
+ evcnt_attach_dynamic(&sc->sc_rxintrcnt, EVCNT_TYPE_INTR,
+ &sc->sc_intrcnt, sc->sc_dev.dv_xname, "rx intr");
+ evcnt_attach_dynamic(&sc->sc_txintrcnt, EVCNT_TYPE_INTR,
+ &sc->sc_intrcnt, sc->sc_dev.dv_xname, "tx intr");
+ evcnt_attach_dynamic(&sc->sc_txdraincnt, EVCNT_TYPE_INTR,
+ &sc->sc_intrcnt, sc->sc_dev.dv_xname, "tx drain");
+ evcnt_attach_dynamic(&sc->sc_nobufintrcnt, EVCNT_TYPE_INTR,
+ &sc->sc_intrcnt, sc->sc_dev.dv_xname, "nobuf intr");
+ evcnt_attach_dynamic(&sc->sc_nointrcnt, EVCNT_TYPE_INTR,
+ &sc->sc_intrcnt, sc->sc_dev.dv_xname, "no intr");
/*
* Create ring loops of the buffer chains.
@@ -271,7 +281,7 @@ zeinit(sc)
if (zereset(sc))
return;
- sc->sc_nexttx = sc->sc_inq = sc->sc_lastack = 0;
+ sc->sc_nexttx = sc->sc_inq = sc->sc_lastack = sc->sc_txcnt = 0;
/*
* Release and init transmit descriptors.
*/
@@ -318,9 +328,10 @@ zestart(ifp)
struct ze_cdata *zc = sc->sc_zedata;
paddr_t buffer;
struct mbuf *m;
- int nexttx, len, i, totlen, error;
+ int nexttx, starttx;
+ int len, i, totlen, error;
int old_inq = sc->sc_inq;
- short orword;
+ uint16_t orword, tdr;
bus_dmamap_t map;
while (sc->sc_inq < (TXDESCS - 1)) {
@@ -361,27 +372,33 @@ zestart(ifp)
*/
totlen = 0;
orword = ZE_TDES1_FS;
+ starttx = nexttx;
for (i = 0; i < map->dm_nsegs; i++) {
buffer = map->dm_segs[i].ds_addr;
len = map->dm_segs[i].ds_len;
- if (len == 0)
- continue;
+ KASSERT(len > 0);
totlen += len;
/* Word alignment calc */
if (totlen == m->m_pkthdr.len) {
- orword |= ZE_TDES1_LS | ZE_TDES1_IC;
+ sc->sc_txcnt += map->dm_nsegs;
+ if (sc->sc_txcnt >= TXDESCS * 3 / 4) {
+ orword |= ZE_TDES1_IC;
+ sc->sc_txcnt = 0;
+ }
+ orword |= ZE_TDES1_LS;
sc->sc_txmbuf[nexttx] = m;
}
zc->zc_xmit[nexttx].ze_bufsize = len;
zc->zc_xmit[nexttx].ze_bufaddr = (char *)buffer;
zc->zc_xmit[nexttx].ze_tdes1 = orword;
- zc->zc_xmit[nexttx].ze_tdr = ZE_TDR_OW;
+ zc->zc_xmit[nexttx].ze_tdr = tdr;
if (++nexttx == TXDESCS)
nexttx = 0;
orword = 0;
+ tdr = ZE_TDR_OW;
}
sc->sc_inq += map->dm_nsegs;
@@ -391,6 +408,10 @@ zestart(ifp)
if (totlen != m->m_pkthdr.len)
panic("zestart: len fault");
#endif
+ /*
+ * Turn ownership of the packet over to the device.
+ */
+ zc->zc_xmit[starttx].ze_tdr = ZE_TDR_OW;
/*
* Kick off the transmit logic, if it is stopped.
@@ -416,11 +437,17 @@ sgec_intr(sc)
int csr, len;
csr = ZE_RCSR(ZE_CSR5);
- if ((csr & ZE_NICSR5_IS) == 0) /* Wasn't we */
+ if ((csr & ZE_NICSR5_IS) == 0) { /* Wasn't we */
+ sc->sc_nointrcnt.ev_count++;
return 0;
+ }
ZE_WCSR(ZE_CSR5, csr);
+ if (csr & ZE_NICSR5_RU)
+ sc->sc_nobufintrcnt.ev_count++;
+
if (csr & ZE_NICSR5_RI) {
+ sc->sc_rxintrcnt.ev_count++;
while ((zc->zc_recv[sc->sc_nextrx].ze_framelen &
ZE_FRAMELEN_OW) == 0) {
@@ -446,13 +473,15 @@ sgec_intr(sc)
}
}
- if (csr & ZE_NICSR5_TI) {
- int lastack = sc->sc_lastack;
- while ((zc->zc_xmit[lastack].ze_tdr & ZE_TDR_OW) == 0) {
+ if (csr & ZE_NICSR5_TI)
+ sc->sc_txintrcnt.ev_count++;
+ if (sc->sc_lastack != sc->sc_nexttx) {
+ int lastack;
+ for (lastack = sc->sc_lastack; lastack != sc->sc_nexttx; ) {
bus_dmamap_t map;
int nlastack;
- if (lastack == sc->sc_nexttx)
+ if ((zc->zc_xmit[lastack].ze_tdr & ZE_TDR_OW) != 0)
break;
if ((zc->zc_xmit[lastack].ze_tdes1 & ZE_TDES1_DT) ==
@@ -470,6 +499,10 @@ sgec_intr(sc)
if (zc->zc_xmit[nlastack].ze_tdr & ZE_TDR_OW)
break;
lastack = nlastack;
+ if (sc->sc_txcnt > map->dm_nsegs)
+ sc->sc_txcnt -= map->dm_nsegs;
+ else
+ sc->sc_txcnt = 0;
sc->sc_inq -= map->dm_nsegs;
KASSERT(zc->zc_xmit[lastack].ze_tdes1 & ZE_TDES1_LS);
ifp->if_opackets++;
@@ -484,11 +517,14 @@ sgec_intr(sc)
if (++lastack == TXDESCS)
lastack = 0;
}
- sc->sc_lastack = lastack;
- if (sc->sc_inq == 0)
- ifp->if_timer = 0;
- ifp->if_flags &= ~IFF_OACTIVE;
- zestart(ifp); /* Put in more in queue */
+ if (lastack != sc->sc_lastack) {
+ sc->sc_txdraincnt.ev_count++;
+ sc->sc_lastack = lastack;
+ if (sc->sc_inq == 0)
+ ifp->if_timer = 0;
+ ifp->if_flags &= ~IFF_OACTIVE;
+ zestart(ifp); /* Put in more in queue */
+ }
}
return 1;
}
diff --git a/sys/dev/ic/sgecvar.h b/sys/dev/ic/sgecvar.h
index 201143faf6d..9ce1a360206 100644
--- a/sys/dev/ic/sgecvar.h
+++ b/sys/dev/ic/sgecvar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: sgecvar.h,v 1.6 2005/12/11 12:21:28 christos Exp $ */
+/* $NetBSD: sgecvar.h,v 1.7 2007/04/26 23:08:22 matt Exp $ */
/*
* Copyright (c) 1999 Ludd, University of Lule}, Sweden. All rights reserved.
*
@@ -47,6 +47,11 @@ struct ze_cdata {
struct ze_softc {
struct device sc_dev; /* Configuration common part */
struct evcnt sc_intrcnt; /* Interrupt counters */
+ struct evcnt sc_rxintrcnt; /* Interrupt counters */
+ struct evcnt sc_txintrcnt; /* Interrupt counters */
+ struct evcnt sc_txdraincnt; /* Interrupt counters */
+ struct evcnt sc_nobufintrcnt; /* Interrupt counters */
+ struct evcnt sc_nointrcnt; /* Interrupt counters */
struct ethercom sc_ec; /* Ethernet common part */
#define sc_if sc_ec.ec_if /* network-visible interface */
bus_space_tag_t sc_iot;
@@ -61,6 +66,7 @@ struct ze_softc {
bus_dmamap_t sc_rcvmap[RXDESCS];
int sc_intvec; /* Interrupt vector */
int sc_nexttx;
+ int sc_txcnt;
int sc_inq;
int sc_lastack;
int sc_nextrx;