Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/mips/sibyte/dev Fix pass3 Tx DMA - when an mbuf spa...
details: https://anonhg.NetBSD.org/src/rev/e60a0c2207ba
branches: trunk
changeset: 559463:e60a0c2207ba
user: simonb <simonb%NetBSD.org@localhost>
date: Thu Mar 18 05:57:58 2004 +0000
description:
Fix pass3 Tx DMA - when an mbuf spans a page boundary, make sure that
it either is sitting in contiguous physical RAM or split the mbuf
into two Tx descriptors. Not the prettiest patch, but works well in
practice - gets about an 8% decrease on CPU time for a simple ttcp TCP
Tx benchmark. Thanks to Chris Demetriou for some debugging help.
Add some event counters.
Remove some #if 0'd debug code.
diffstat:
sys/arch/mips/sibyte/dev/sbmac.c | 119 ++++++++++++++++++++++++++++----------
1 files changed, 88 insertions(+), 31 deletions(-)
diffs (244 lines):
diff -r c4e0be6588ba -r e60a0c2207ba sys/arch/mips/sibyte/dev/sbmac.c
--- a/sys/arch/mips/sibyte/dev/sbmac.c Thu Mar 18 03:32:03 2004 +0000
+++ b/sys/arch/mips/sibyte/dev/sbmac.c Thu Mar 18 05:57:58 2004 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sbmac.c,v 1.14 2004/03/14 10:55:45 simonb Exp $ */
+/* $NetBSD: sbmac.c,v 1.15 2004/03/18 05:57:58 simonb Exp $ */
/*
* Copyright 2000, 2001
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sbmac.c,v 1.14 2004/03/14 10:55:45 simonb Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sbmac.c,v 1.15 2004/03/18 05:57:58 simonb Exp $");
#include "bpfilter.h"
#include "opt_inet.h"
@@ -83,7 +83,6 @@
#include <mips/sibyte/include/sb1250_dma.h>
#include <mips/sibyte/include/sb1250_scd.h>
-
/* Simple types */
typedef u_long sbmac_port_t;
@@ -105,6 +104,8 @@
/* Macros */
+#define SBMAC_EVENT_COUNTERS /* Include counters for various events */
+
#define SBDMA_NEXTBUF(d, f) ((((d)->f+1) == (d)->sbdma_dscrtable_end) ? \
(d)->sbdma_dscrtable : (d)->f+1)
@@ -213,9 +214,25 @@
sbmacdma_t sbm_rxdma;
int sbm_pass3_dma; /* chip has pass3 SOC DMA features */
+
+#ifdef SBMAC_EVENT_COUNTERS
+ struct evcnt sbm_ev_rxintr; /* Rx interrupts */
+ struct evcnt sbm_ev_txintr; /* Tx interrupts */
+ struct evcnt sbm_ev_txdrop; /* Tx dropped due to no mbuf alloc failed */
+ struct evcnt sbm_ev_txstall; /* Tx stalled due to no descriptors free */
+
+ struct evcnt sbm_ev_txsplit; /* pass3 Tx split mbuf */
+ struct evcnt sbm_ev_txkeep; /* pass3 Tx didn't split mbuf */
+#endif
};
+#ifdef SBMAC_EVENT_COUNTERS
+#define SBMAC_EVCNT_INCR(ev) (ev).ev_count++
+#else
+#define SBMAC_EVCNT_INCR(ev) do { /* nothing */ } while (0)
+#endif
+
/* Externs */
extern paddr_t kvtophys(vaddr_t);
@@ -593,22 +610,10 @@
* the ring, the ring is full
*/
- if (nextdsc == d->sbdma_remptr)
+ if (nextdsc == d->sbdma_remptr) {
+ SBMAC_EVCNT_INCR(sc->sbm_ev_txstall);
return ENOSPC;
-
-#if 0
- do {
- struct mbuf *m0;
-
- printf("mbuf chain: ");
- for (m0 = m; m0 != 0; m0 = m0->m_next) {
- printf("%d%c/%X ", m0->m_len,
- m0->m_flags & M_EXT ? 'X' : 'N',
- mtod(m0, u_int));
- }
- printf("\n");
- } while (0);
-#endif
+ }
/*
* PASS3 parts do not have buffer alignment restriction.
@@ -632,7 +637,8 @@
*/
dsc->dscr_b =
V_DMA_DSCRB_OPTIONS(K_DMA_ETHTX_APPENDCRC_APPENDPAD) |
- V_DMA_DSCRB_A_SIZE((m->m_len + (mtod(m,unsigned int) & 0x0000001F))) |
+ V_DMA_DSCRB_A_SIZE((m->m_len +
+ (mtod(m,unsigned int) & 0x0000001F))) |
V_DMA_DSCRB_PKT_SIZE_MSB( (m->m_pkthdr.len & 0xB000) ) |
V_DMA_DSCRB_PKT_SIZE(m->m_pkthdr.len);
@@ -643,24 +649,50 @@
/* Start with first non-head mbuf */
for(m_temp = m->m_next; m_temp != 0; m_temp = m_temp->m_next) {
+ int len, next_len;
+ uint64_t addr;
if (m_temp->m_len == 0)
continue; /* Skip 0-length mbufs */
+ len = m_temp->m_len;
+ addr = KVTOPHYS(mtod(m_temp, caddr_t));
+
+ /*
+ * Check to see if the mbuf spans a page boundary. If
+ * it does, and the physical pages behind the virtual
+ * pages are not contiguous, split it so that each
+ * virtual page uses it's own Tx descriptor.
+ */
+ if (trunc_page(addr) != trunc_page(addr + len - 1)) {
+ next_len = (addr + len) - trunc_page(addr + len);
+
+ len -= next_len;
+
+ if (addr + len ==
+ KVTOPHYS(mtod(m_temp, caddr_t) + len)) {
+ SBMAC_EVCNT_INCR(sc->sbm_ev_txkeep);
+ len += next_len;
+ next_len = 0;
+ } else {
+ SBMAC_EVCNT_INCR(sc->sbm_ev_txsplit);
+ }
+ } else {
+ next_len = 0;
+ }
+
+again:
/*
* fill in the descriptor
*/
-
- dsc->dscr_a = KVTOPHYS(mtod(m_temp,caddr_t)) |
- M_DMA_DSCRA_INTERRUPT;
+ dsc->dscr_a = addr | M_DMA_DSCRA_INTERRUPT;
/*
* transmitting: set outbound options,buffer A
* size(+ low 5 bits of start addr)
*/
dsc->dscr_b = V_DMA_DSCRB_OPTIONS(K_DMA_ETHTX_NOTSOP) |
- V_DMA_DSCRB_A_SIZE( (m_temp->m_len +
- (mtod(m_temp,unsigned int) & 0x0000001F)) );
+ V_DMA_DSCRB_A_SIZE((len + (addr & 0x0000001F)));
d->sbdma_ctxtable[dsc-d->sbdma_dscrtable] = NULL;
@@ -670,6 +702,7 @@
nextdsc = SBDMA_NEXTBUF(d,sbdma_addptr);
if (nextdsc == d->sbdma_remptr) {
d->sbdma_addptr = origdesc;
+ SBMAC_EVCNT_INCR(sc->sbm_ev_txstall);
return ENOSPC;
}
d->sbdma_addptr = nextdsc;
@@ -677,8 +710,16 @@
prevdsc = dsc;
dsc = d->sbdma_addptr;
num_mbufs++;
+
+ if (next_len != 0) {
+ addr = KVTOPHYS(mtod(m_temp, caddr_t) + len);
+ len = next_len;
+
+ next_len = 0;
+ goto again;
+ }
+
}
-
/*Set head mbuf to last context index*/
d->sbdma_ctxtable[prevdsc-d->sbdma_dscrtable] = m;
} else {
@@ -694,6 +735,7 @@
if (m_new == NULL) {
printf("%s: mbuf allocation failed\n",
d->sbdma_eth->sc_dev.dv_xname);
+ SBMAC_EVCNT_INCR(sc->sbm_ev_txdrop);
return ENOBUFS;
}
@@ -702,6 +744,7 @@
printf("%s: mbuf cluster allocation failed\n",
d->sbdma_eth->sc_dev.dv_xname);
m_freem(m_new);
+ SBMAC_EVCNT_INCR(sc->sbm_ev_txdrop);
return ENOBUFS;
}
@@ -1077,12 +1120,22 @@
SYS_SOC_TYPE(sysrev) == K_SYS_SOC_TYPE_BCM1125H ||
(SYS_SOC_TYPE(sysrev) == K_SYS_SOC_TYPE_BCM1250 &&
0));
+#ifdef SBMAC_EVENT_COUNTERS
+ evcnt_attach_dynamic(&s->sbm_ev_rxintr, EVCNT_TYPE_INTR,
+ NULL, s->sc_dev.dv_xname, "rxintr");
+ evcnt_attach_dynamic(&s->sbm_ev_txintr, EVCNT_TYPE_INTR,
+ NULL, s->sc_dev.dv_xname, "txintr");
+ evcnt_attach_dynamic(&s->sbm_ev_txdrop, EVCNT_TYPE_MISC,
+ NULL, s->sc_dev.dv_xname, "txdrop");
+ evcnt_attach_dynamic(&s->sbm_ev_txstall, EVCNT_TYPE_MISC,
+ NULL, s->sc_dev.dv_xname, "txstall");
if (s->sbm_pass3_dma) {
- printf("\n");
- printf("%s: disabling unaligned tx DMA\n", s->sc_dev.dv_xname);
- printf("%s", s->sc_dev.dv_xname);
- s->sbm_pass3_dma = 0;
+ evcnt_attach_dynamic(&s->sbm_ev_txsplit, EVCNT_TYPE_MISC,
+ NULL, s->sc_dev.dv_xname, "pass3tx-split");
+ evcnt_attach_dynamic(&s->sbm_ev_txkeep, EVCNT_TYPE_MISC,
+ NULL, s->sc_dev.dv_xname, "pass3tx-keep");
}
+#endif
}
/*
@@ -1706,15 +1759,19 @@
* Transmits on channel 0
*/
- if (isr & (M_MAC_INT_CHANNEL << S_MAC_TX_CH0))
+ if (isr & (M_MAC_INT_CHANNEL << S_MAC_TX_CH0)) {
sbdma_tx_process(sc, &(sc->sbm_txdma));
+ SBMAC_EVCNT_INCR(sc->sbm_ev_txintr);
+ }
/*
* Receives on channel 0
*/
- if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0))
+ if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) {
sbdma_rx_process(sc, &(sc->sbm_rxdma));
+ SBMAC_EVCNT_INCR(sc->sbm_ev_rxintr);
+ }
}
/* try to get more packets going */
Home |
Main Index |
Thread Index |
Old Index