summaryrefslogtreecommitdiffstats
path: root/sys/pci
diff options
context:
space:
mode:
authorluigi <luigi@FreeBSD.org>2001-11-28 16:10:37 +0000
committerluigi <luigi@FreeBSD.org>2001-11-28 16:10:37 +0000
commite77127c5fa0b17ca6ef8389b263355ea4466246d (patch)
treee997085ab0a364eeeaaa81956bafb38386380947 /sys/pci
parent35b8c147a06c30d20838fe10f003bfd8bc1af4d6 (diff)
downloadFreeBSD-src-e77127c5fa0b17ca6ef8389b263355ea4466246d.zip
FreeBSD-src-e77127c5fa0b17ca6ef8389b263355ea4466246d.tar.gz
Remove the need for an expensive m_devget on the i386, which does not
have alignment problems. On small boxes (e.g. the net4501 from Soekris, featuring a 486/133) this provides huge performance benefits: the peak forwarding rate with avg.sized packets goes up by 50-70% because of this change alone. Faster CPUs might benefit less from this change, but in any case the CPU has better things to do than waste time on useless memory-to-memory copies. Several drivers (for Tulip-like cards) might benefit from a similar change. Right now the new behaviour is controlled by a sysctl variable, hw.sis_quick which defaults to 1 (on), you can set it to 0 to reintroduce the old behaviour (and compare the results). The variable is only there to show how much you can gain with this change, it will go away soon. Also, slightly simplify the code to initialize the ring buffers, and remove a couple of dangerous printf's which could trigger on any packet in case of mbuf shortage. MFC-after: 3 days
Diffstat (limited to 'sys/pci')
-rw-r--r--sys/pci/if_sis.c80
1 files changed, 41 insertions, 39 deletions
diff --git a/sys/pci/if_sis.c b/sys/pci/if_sis.c
index a924e99..196e1f9 100644
--- a/sys/pci/if_sis.c
+++ b/sys/pci/if_sis.c
@@ -64,6 +64,7 @@
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/socket.h>
+#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_arp.h>
@@ -198,6 +199,12 @@ static driver_t sis_driver = {
static devclass_t sis_devclass;
+#ifdef __i386__
+static int sis_quick=1;
+SYSCTL_INT(_hw, OID_AUTO, sis_quick, CTLFLAG_RW,
+ &sis_quick,0,"do not mdevget in sis driver");
+#endif
+
DRIVER_MODULE(if_sis, pci, sis_driver, sis_devclass, 0, 0);
DRIVER_MODULE(miibus, sis, miibus_driver, miibus_devclass, 0, 0);
@@ -1133,27 +1140,19 @@ static int sis_list_tx_init(sc)
{
struct sis_list_data *ld;
struct sis_ring_data *cd;
- int i;
+ int i, nexti;
cd = &sc->sis_cdata;
ld = &sc->sis_ldata;
for (i = 0; i < SIS_TX_LIST_CNT; i++) {
- if (i == (SIS_TX_LIST_CNT - 1)) {
- ld->sis_tx_list[i].sis_nextdesc =
- &ld->sis_tx_list[0];
- bus_dmamap_load(sc->sis_ldata.sis_tx_tag,
- sc->sis_ldata.sis_tx_dmamap, &ld->sis_tx_list[0],
- sizeof(struct sis_desc), sis_dma_map_desc_next,
- &ld->sis_tx_list[i], 0);
- } else {
+ nexti = (i == (SIS_TX_LIST_CNT - 1)) ? 0 : i+1 ;
ld->sis_tx_list[i].sis_nextdesc =
- &ld->sis_tx_list[i + 1];
+ &ld->sis_tx_list[nexti];
bus_dmamap_load(sc->sis_ldata.sis_tx_tag,
sc->sis_ldata.sis_tx_dmamap,
- &ld->sis_tx_list[i + 1], sizeof(struct sis_desc),
+ &ld->sis_tx_list[nexti], sizeof(struct sis_desc),
sis_dma_map_desc_next, &ld->sis_tx_list[i], 0);
- }
ld->sis_tx_list[i].sis_mbuf = NULL;
ld->sis_tx_list[i].sis_ptr = 0;
ld->sis_tx_list[i].sis_ctl = 0;
@@ -1177,7 +1176,7 @@ static int sis_list_rx_init(sc)
{
struct sis_list_data *ld;
struct sis_ring_data *cd;
- int i;
+ int i,nexti;
ld = &sc->sis_ldata;
cd = &sc->sis_cdata;
@@ -1185,24 +1184,15 @@ static int sis_list_rx_init(sc)
for (i = 0; i < SIS_RX_LIST_CNT; i++) {
if (sis_newbuf(sc, &ld->sis_rx_list[i], NULL) == ENOBUFS)
return(ENOBUFS);
- if (i == (SIS_RX_LIST_CNT - 1)) {
+ nexti = (i == (SIS_RX_LIST_CNT - 1)) ? 0 : i+1 ;
ld->sis_rx_list[i].sis_nextdesc =
- &ld->sis_rx_list[0];
- bus_dmamap_load(sc->sis_ldata.sis_rx_tag,
- sc->sis_ldata.sis_rx_dmamap, &ld->sis_rx_list[0],
- sizeof(struct sis_desc), sis_dma_map_desc_next,
- &ld->sis_rx_list[i], 0);
-
- } else {
- ld->sis_rx_list[i].sis_nextdesc =
- &ld->sis_rx_list[i + 1];
+ &ld->sis_rx_list[nexti];
bus_dmamap_load(sc->sis_ldata.sis_rx_tag,
sc->sis_ldata.sis_rx_dmamap,
- &ld->sis_rx_list[i + 1],
+ &ld->sis_rx_list[nexti],
sizeof(struct sis_desc), sis_dma_map_desc_next,
&ld->sis_rx_list[i], 0);
}
- }
bus_dmamap_sync(sc->sis_ldata.sis_rx_tag,
sc->sis_ldata.sis_rx_dmamap, BUS_DMASYNC_PREWRITE);
@@ -1227,16 +1217,11 @@ static int sis_newbuf(sc, c, m)
if (m == NULL) {
MGETHDR(m_new, M_DONTWAIT, MT_DATA);
- if (m_new == NULL) {
- printf("sis%d: no memory for rx list "
- "-- packet dropped!\n", sc->sis_unit);
+ if (m_new == NULL)
return(ENOBUFS);
- }
MCLGET(m_new, M_DONTWAIT);
if (!(m_new->m_flags & M_EXT)) {
- printf("sis%d: no memory for rx list "
- "-- packet dropped!\n", sc->sis_unit);
m_freem(m_new);
return(ENOBUFS);
}
@@ -1279,7 +1264,6 @@ static void sis_rxeof(sc)
i = sc->sis_cdata.sis_rx_prod;
while(SIS_OWNDESC(&sc->sis_ldata.sis_rx_list[i])) {
- struct mbuf *m0 = NULL;
cur_rx = &sc->sis_ldata.sis_rx_list[i];
rxstat = cur_rx->sis_rxstat;
@@ -1307,14 +1291,32 @@ static void sis_rxeof(sc)
}
/* No errors; receive the packet. */
- m0 = m_devget(mtod(m, char *), total_len, ETHER_ALIGN, ifp,
- NULL);
- sis_newbuf(sc, cur_rx, m);
- if (m0 == NULL) {
- ifp->if_ierrors++;
- continue;
+#ifdef __i386__
+ /*
+ * On the x86 we do not have alignment problems, so try to
+ * allocate a new buffer for the receive ring, and pass up
+ * the one where the packet is already, saving the expensive
+ * copy done in m_devget().
+ * If we are on an architecture with alignment problems, or
+ * if the allocation fails, then use m_devget and leave the
+ * existing buffer in the receive ring.
+ */
+ if (sis_quick && sis_newbuf(sc, cur_rx, NULL) == 0) {
+ m->m_pkthdr.rcvif = ifp;
+ m->m_pkthdr.len = m->m_len = total_len;
+ } else
+#endif
+ {
+ struct mbuf *m0;
+ m0 = m_devget(mtod(m, char *), total_len,
+ ETHER_ALIGN, ifp, NULL);
+ sis_newbuf(sc, cur_rx, m);
+ if (m0 == NULL) {
+ ifp->if_ierrors++;
+ continue;
+ }
+ m = m0;
}
- m = m0;
ifp->if_ipackets++;
eh = mtod(m, struct ether_header *);
OpenPOWER on IntegriCloud