summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad Smith <brad@cvs.openbsd.org>2005-11-19 23:04:49 +0000
committerBrad Smith <brad@cvs.openbsd.org>2005-11-19 23:04:49 +0000
commit9ee030d166954ee9f2e8a6eb27dc210c97c415c9 (patch)
tree231476c5471705baf81cf151f79208ac83ac6a6b
parent98d8ec722dc1f84eb7bdfda92701982e3198bc77 (diff)
Correct a performance bug from Bill Paul's original FreeBSD bge(4) driver:
Each call to the FreeBSD bge_start() routine the transmit producer pointer index from the chip mailbox register BGE_MBX_TX_HOST_PROD0_LO. The local copy of that value is then updated by bge_encap() as bge_encap() encapsulates packets in the Tx ring. If bge_encap() succeds in encpuslating one or more packets, bge_start() tells the chip to start sending the newly-encinitiates writes the new value back to the chip mailbox register. However, comparison of the Linux drivers (Broadcom-supplied and open-source tg3.c) and to the OpenSolaris driver confirms that register BGE_MBX_TX_HOST_PROD0_LO is write-only to software. Thus, we can just keep a copy in the softc, and eliminate the (expensive) PCI register write on each call to bge_start(). From jonathan NetBSD tested by krw@, sturm@ and I on a few different bge NICs.
-rw-r--r--sys/dev/pci/if_bge.c16
-rw-r--r--sys/dev/pci/if_bgereg.h3
2 files changed, 13 insertions, 6 deletions
diff --git a/sys/dev/pci/if_bge.c b/sys/dev/pci/if_bge.c
index de2904e4ef7..2172301074d 100644
--- a/sys/dev/pci/if_bge.c
+++ b/sys/dev/pci/if_bge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bge.c,v 1.92 2005/11/14 13:11:40 mickey Exp $ */
+/* $OpenBSD: if_bge.c,v 1.93 2005/11/19 23:04:48 brad Exp $ */
/*
* Copyright (c) 2001 Wind River Systems
@@ -1058,10 +1058,14 @@ bge_init_tx_ring(struct bge_softc *sc)
sc->bge_txcnt = 0;
sc->bge_tx_saved_considx = 0;
- CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, 0);
+
+ /* Initialize transmit producer index for host-memory send ring. */
+ sc->bge_tx_prodidx = 0;
+ CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, sc->bge_tx_prodidx);
if (sc->bge_quirks & BGE_QUIRK_PRODUCER_BUG)
- CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, 0);
+ CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, sc->bge_tx_prodidx);
+ /* NIC-memory send ring not used; initialize to zero. */
CSR_WRITE_4(sc, BGE_MBX_TX_NIC_PROD0_LO, 0);
if (sc->bge_quirks & BGE_QUIRK_PRODUCER_BUG)
CSR_WRITE_4(sc, BGE_MBX_TX_NIC_PROD0_LO, 0);
@@ -2805,7 +2809,7 @@ bge_start(struct ifnet *ifp)
{
struct bge_softc *sc;
struct mbuf *m_head = NULL;
- u_int32_t prodidx = 0;
+ u_int32_t prodidx;
int pkts = 0;
sc = ifp->if_softc;
@@ -2813,7 +2817,7 @@ bge_start(struct ifnet *ifp)
if (!sc->bge_link && ifp->if_snd.ifq_len < 10)
return;
- prodidx = CSR_READ_4(sc, BGE_MBX_TX_HOST_PROD0_LO);
+ prodidx = sc->bge_tx_prodidx;
while(sc->bge_cdata.bge_tx_chain[prodidx] == NULL) {
IFQ_POLL(&ifp->if_snd, m_head);
@@ -2870,6 +2874,8 @@ bge_start(struct ifnet *ifp)
if (sc->bge_quirks & BGE_QUIRK_PRODUCER_BUG)
CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx);
+ sc->bge_tx_prodidx = prodidx;
+
/*
* Set a timeout in case the chip goes out to lunch.
*/
diff --git a/sys/dev/pci/if_bgereg.h b/sys/dev/pci/if_bgereg.h
index d0962d8a1a0..8ab2b8f0344 100644
--- a/sys/dev/pci/if_bgereg.h
+++ b/sys/dev/pci/if_bgereg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bgereg.h,v 1.30 2005/10/09 23:41:55 brad Exp $ */
+/* $OpenBSD: if_bgereg.h,v 1.31 2005/11/19 23:04:48 brad Exp $ */
/*
* Copyright (c) 2001 Wind River Systems
@@ -2328,6 +2328,7 @@ struct bge_softc {
u_int16_t bge_rx_saved_considx;
u_int16_t bge_ev_saved_considx;
u_int16_t bge_return_ring_cnt;
+ u_int32_t bge_tx_prodidx;
u_int16_t bge_std; /* current std ring head */
u_int16_t bge_jumbo; /* current jumo ring head */
SLIST_HEAD(__bge_jfreehead, bge_jpool_entry) bge_jfree_listhead;