diff options
author | Brad Smith <brad@cvs.openbsd.org> | 2005-11-19 23:04:49 +0000 |
---|---|---|
committer | Brad Smith <brad@cvs.openbsd.org> | 2005-11-19 23:04:49 +0000 |
commit | 9ee030d166954ee9f2e8a6eb27dc210c97c415c9 (patch) | |
tree | 231476c5471705baf81cf151f79208ac83ac6a6b | |
parent | 98d8ec722dc1f84eb7bdfda92701982e3198bc77 (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.c | 16 | ||||
-rw-r--r-- | sys/dev/pci/if_bgereg.h | 3 |
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; |