diff options
author | luigi <luigi@FreeBSD.org> | 2001-11-28 16:10:37 +0000 |
---|---|---|
committer | luigi <luigi@FreeBSD.org> | 2001-11-28 16:10:37 +0000 |
commit | e77127c5fa0b17ca6ef8389b263355ea4466246d (patch) | |
tree | e997085ab0a364eeeaaa81956bafb38386380947 | |
parent | 35b8c147a06c30d20838fe10f003bfd8bc1af4d6 (diff) | |
download | FreeBSD-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
-rw-r--r-- | sys/pci/if_sis.c | 80 |
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 *); |