Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 13 Oct 2005 08:13:10 -0700
From:      Sean McNeil <sean@mcneil.com>
To:        Mike Tancsa <mike@sentex.net>
Cc:        freebsd-amd64@freebsd.org
Subject:   realtek performance (was Re: good ATI chipset results)
Message-ID:  <1129216390.8681.6.camel@server.mcneil.com>
In-Reply-To: <6.2.3.4.0.20051013090818.07a5c9a0@64.7.153.2>
References:  <6.2.3.4.0.20051013090818.07a5c9a0@64.7.153.2>

next in thread | previous in thread | raw e-mail | index | archive | help

--=-bBWu23haOdgH96FR+ng9
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

On Thu, 2005-10-13 at 09:17 -0400, Mike Tancsa wrote:
> Havent really seen anyone else use this board, but I have had good 
> luck with it so far
> 
> http://www.ecs.com.tw/ECSWeb/Products/ProductsDetail.aspx?DetailID=506&MenuID=90&LanID=0
> 
> Its a micro ATX formfactor with built in video and the onboard NIC is 
> a realtek.  (Although its not the fastest NIC, its driver is stable 
> and mature-- especially compared to the headaches people seem to have 
> with the NVIDIA NICs.)

Is this the RealTek 8169S Single-chip Gigabit Ethernet?

For those interested, here are some changes I always use to increase the
performance of the above NIC.  With these mods, I can stream over 20
MBps video multicast and do other stuff over the network without issues.
Without the changes, xmit is horrible with severe UDP packet loss.

Cheers,
Sean


--=-bBWu23haOdgH96FR+ng9
Content-Disposition: attachment; filename=if_rlreg.h.diff
Content-Type: text/x-patch; name=if_rlreg.h.diff; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

--- /sys/pci/if_rlreg.h	Thu Oct  6 13:17:17 2005
+++ ./if_rlreg.h	Thu Oct  6 15:01:42 2005
@@ -618,13 +618,8 @@
 #define RE_FIXUP_RX	1
 #endif
 
-#define RL_TX_DESC_CNT		64
-#define RL_RX_DESC_CNT		RL_TX_DESC_CNT
-#define RL_RX_LIST_SZ		(RL_RX_DESC_CNT * sizeof(struct rl_desc))
-#define RL_TX_LIST_SZ		(RL_TX_DESC_CNT * sizeof(struct rl_desc))
 #define RL_RING_ALIGN		256
 #define RL_IFQ_MAXLEN		512
-#define RL_DESC_INC(x)		(x = (x + 1) % RL_TX_DESC_CNT)
 #define RL_OWN(x)		(le32toh((x)->rl_cmdstat) & RL_RDESC_STAT_OWN)
 #define RL_RXBYTES(x)		(le32toh((x)->rl_cmdstat) & sc->rl_rxlenmask)
 #define RL_PKTSZ(x)		((x)/* >> 3*/)
@@ -654,14 +649,15 @@
 };
 
 struct rl_list_data {
-	struct mbuf		*rl_tx_mbuf[RL_TX_DESC_CNT];
-	struct mbuf		*rl_rx_mbuf[RL_TX_DESC_CNT];
+	int			rl_desc_count;
+	struct mbuf		**rl_tx_mbuf;
+	struct mbuf		**rl_rx_mbuf;
 	int			rl_tx_prodidx;
 	int			rl_rx_prodidx;
 	int			rl_tx_considx;
 	int			rl_tx_free;
-	bus_dmamap_t		rl_tx_dmamap[RL_TX_DESC_CNT];
-	bus_dmamap_t		rl_rx_dmamap[RL_RX_DESC_CNT];
+	bus_dmamap_t		*rl_tx_dmamap;
+	bus_dmamap_t		*rl_rx_dmamap;
 	bus_dma_tag_t		rl_mtag;	/* mbuf mapping tag */
 	bus_dma_tag_t		rl_stag;	/* stats mapping tag */
 	bus_dmamap_t		rl_smap;	/* stats map */

--=-bBWu23haOdgH96FR+ng9
Content-Disposition: attachment; filename=if_re.c.diff
Content-Type: text/x-patch; name=if_re.c.diff; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

--- /sys/dev/re/if_re.c	Sat Oct  8 00:35:10 2005
+++ ./if_re.c	Sat Oct  8 09:30:26 2005
@@ -300,6 +300,9 @@
 	CSR_WRITE_1(sc, RL_EECMD,			\
 		CSR_READ_1(sc, RL_EECMD) & ~x)
 
+#define RL_DESC_COUNT(sc)	((sc)->rl_ldata.rl_desc_count)
+#define RL_DESC_INC(sc,x)	(x = (x + 1) % RL_DESC_COUNT(sc))
+
 /*
  * Send a read command and address to the EEPROM, check for ACK.
  */
@@ -917,13 +920,13 @@
 			cmdstat |= RL_TDESC_CMD_SOF;
 		else
 			cmdstat |= RL_TDESC_CMD_OWN;
-		if (idx == (RL_RX_DESC_CNT - 1))
+		if (idx == (RL_DESC_COUNT(ctx->sc) - 1))
 			cmdstat |= RL_TDESC_CMD_EOR;
 		d->rl_cmdstat = htole32(cmdstat | ctx->rl_flags);
 		i++;
 		if (i == nseg)
 			break;
-		RL_DESC_INC(idx);
+		RL_DESC_INC(ctx->sc,idx);
 	}
 
 	d->rl_cmdstat |= htole32(RL_TDESC_CMD_EOF);
@@ -961,10 +964,46 @@
 	int			nseg;
 	int			i;
 
+	sc->rl_ldata.rl_tx_mbuf =
+	    (struct mbuf **) malloc(sizeof(struct mbuf *) * RL_DESC_COUNT(sc),
+				    M_DEVBUF, M_NOWAIT|M_ZERO);
+
+	if (sc->rl_ldata.rl_tx_mbuf == NULL) {
+		device_printf(dev, "could not allocate tx mbuf list\n");
+		return (ENOMEM);
+	}
+
+	sc->rl_ldata.rl_rx_mbuf =
+	    (struct mbuf **) malloc(sizeof(struct mbuf *) * RL_DESC_COUNT(sc),
+				    M_DEVBUF, M_NOWAIT|M_ZERO);
+
+	if (sc->rl_ldata.rl_rx_mbuf == NULL) {
+		device_printf(dev, "could not allocate rx mbuf list\n");
+		return (ENOMEM);
+	}
+
+	sc->rl_ldata.rl_tx_dmamap =
+	    (bus_dmamap_t *) malloc(sizeof(bus_dmamap_t) * RL_DESC_COUNT(sc),
+				    M_DEVBUF, M_NOWAIT|M_ZERO);
+
+	if (sc->rl_ldata.rl_tx_dmamap == NULL) {
+		device_printf(dev, "could not allocate tx dmamap list\n");
+		return (ENOMEM);
+	}
+
+	sc->rl_ldata.rl_rx_dmamap =
+	    (bus_dmamap_t *) malloc(sizeof(bus_dmamap_t) * RL_DESC_COUNT(sc),
+				    M_DEVBUF, M_NOWAIT|M_ZERO);
+
+	if (sc->rl_ldata.rl_rx_dmamap == NULL) {
+		device_printf(dev, "could not allocate rx dmamap list\n");
+		return (ENOMEM);
+	}
+
 	/*
 	 * Allocate map for RX mbufs.
 	 */
-	nseg = 32;
+	nseg = RL_DESC_COUNT(sc);
 	error = bus_dma_tag_create(sc->rl_parent_tag, ETHER_ALIGN, 0,
 	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
 	    NULL, MCLBYTES * nseg, nseg, MCLBYTES, BUS_DMA_ALLOCNOW,
@@ -979,7 +1018,9 @@
 	 */
 	error = bus_dma_tag_create(sc->rl_parent_tag, RL_RING_ALIGN,
 	    0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
-	    NULL, RL_TX_LIST_SZ, 1, RL_TX_LIST_SZ, BUS_DMA_ALLOCNOW,
+	    NULL, RL_DESC_COUNT(sc) * sizeof(struct rl_desc), 1,
+	    RL_DESC_COUNT(sc) * sizeof(struct rl_desc),
+	    BUS_DMA_ALLOCNOW | BUS_DMA_COHERENT,
 	    NULL, NULL, &sc->rl_ldata.rl_tx_list_tag);
 	if (error) {
 		device_printf(dev, "could not allocate dma tag\n");
@@ -998,12 +1039,12 @@
 
 	error = bus_dmamap_load(sc->rl_ldata.rl_tx_list_tag,
 	     sc->rl_ldata.rl_tx_list_map, sc->rl_ldata.rl_tx_list,
-	     RL_TX_LIST_SZ, re_dma_map_addr,
+	     RL_DESC_COUNT(sc) * sizeof(struct rl_desc), re_dma_map_addr,
 	     &sc->rl_ldata.rl_tx_list_addr, BUS_DMA_NOWAIT);
 
 	/* Create DMA maps for TX buffers */
 
-	for (i = 0; i < RL_TX_DESC_CNT; i++) {
+	for (i = 0; i < RL_DESC_COUNT(sc); i++) {
 		error = bus_dmamap_create(sc->rl_ldata.rl_mtag, 0,
 			    &sc->rl_ldata.rl_tx_dmamap[i]);
 		if (error) {
@@ -1017,7 +1058,9 @@
 	 */
 	error = bus_dma_tag_create(sc->rl_parent_tag, RL_RING_ALIGN,
 	    0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
-	    NULL, RL_RX_LIST_SZ, 1, RL_RX_LIST_SZ, BUS_DMA_ALLOCNOW,
+	    NULL, RL_DESC_COUNT(sc) * sizeof(struct rl_desc), 1,
+	    RL_DESC_COUNT(sc) * sizeof(struct rl_desc),
+	    BUS_DMA_ALLOCNOW | BUS_DMA_COHERENT,
 	    NULL, NULL, &sc->rl_ldata.rl_rx_list_tag);
 	if (error) {
 		device_printf(dev, "could not allocate dma tag\n");
@@ -1036,12 +1079,12 @@
 
 	error = bus_dmamap_load(sc->rl_ldata.rl_rx_list_tag,
 	     sc->rl_ldata.rl_rx_list_map, sc->rl_ldata.rl_rx_list,
-	     RL_RX_LIST_SZ, re_dma_map_addr,
+	     RL_DESC_COUNT(sc) * sizeof(struct rl_desc), re_dma_map_addr,
 	     &sc->rl_ldata.rl_rx_list_addr, BUS_DMA_NOWAIT);
 
 	/* Create DMA maps for RX buffers */
 
-	for (i = 0; i < RL_RX_DESC_CNT; i++) {
+	for (i = 0; i < RL_DESC_COUNT(sc); i++) {
 		error = bus_dmamap_create(sc->rl_ldata.rl_mtag, 0,
 			    &sc->rl_ldata.rl_rx_dmamap[i]);
 		if (error) {
@@ -1122,6 +1165,8 @@
 
 	if (sc->rl_type == RL_8169) {
 
+		RL_DESC_COUNT(sc) = 1024;
+
 		/* Set RX length mask */
 
 		sc->rl_rxlenmask = RL_RDESC_STAT_GFRAGLEN;
@@ -1141,6 +1186,8 @@
 				eaddr[i] = CSR_READ_1(sc, RL_IDR0 + i);
 	} else {
 
+		RL_DESC_COUNT(sc) = 64;
+
 		/* Set RX length mask */
 
 		sc->rl_rxlenmask = RL_RDESC_STAT_FRAGLEN;
@@ -1163,13 +1210,13 @@
 	/*
 	 * Allocate the parent bus DMA tag appropriate for PCI.
 	 */
-#define RL_NSEG_NEW 32
 	error = bus_dma_tag_create(NULL,	/* parent */
 			1, 0,			/* alignment, boundary */
 			BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
 			BUS_SPACE_MAXADDR,	/* highaddr */
 			NULL, NULL,		/* filter, filterarg */
-			MAXBSIZE, RL_NSEG_NEW,	/* maxsize, nsegments */
+			MAXBSIZE,		/* maxsize */
+			RL_DESC_COUNT(sc),	/* nsegments */
 			BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */
 			BUS_DMA_ALLOCNOW,	/* flags */
 			NULL, NULL,		/* lockfunc, lockarg */
@@ -1340,10 +1387,10 @@
 	/* Destroy all the RX and TX buffer maps */
 
 	if (sc->rl_ldata.rl_mtag) {
-		for (i = 0; i < RL_TX_DESC_CNT; i++)
+		for (i = 0; i < RL_DESC_COUNT(sc); i++)
 			bus_dmamap_destroy(sc->rl_ldata.rl_mtag,
 			    sc->rl_ldata.rl_tx_dmamap[i]);
-		for (i = 0; i < RL_RX_DESC_CNT; i++)
+		for (i = 0; i < RL_DESC_COUNT(sc); i++)
 			bus_dmamap_destroy(sc->rl_ldata.rl_mtag,
 			    sc->rl_ldata.rl_rx_dmamap[i]);
 		bus_dma_tag_destroy(sc->rl_ldata.rl_mtag);
@@ -1363,6 +1410,18 @@
 	if (sc->rl_parent_tag)
 		bus_dma_tag_destroy(sc->rl_parent_tag);
 
+	if (sc->rl_ldata.rl_rx_dmamap)
+		free(sc->rl_ldata.rl_rx_dmamap, M_DEVBUF);
+
+	if (sc->rl_ldata.rl_tx_dmamap)
+		free(sc->rl_ldata.rl_tx_dmamap, M_DEVBUF);
+
+	if (sc->rl_ldata.rl_rx_mbuf)
+		free(sc->rl_ldata.rl_rx_mbuf, M_DEVBUF);
+
+	if (sc->rl_ldata.rl_tx_mbuf)
+		free(sc->rl_ldata.rl_tx_mbuf, M_DEVBUF);
+
 	mtx_destroy(&sc->rl_mtx);
 
 	return (0);
@@ -1452,15 +1511,16 @@
 
 	RL_LOCK_ASSERT(sc);
 
-	bzero ((char *)sc->rl_ldata.rl_tx_list, RL_TX_LIST_SZ);
-	bzero ((char *)&sc->rl_ldata.rl_tx_mbuf,
-	    (RL_TX_DESC_CNT * sizeof(struct mbuf *)));
+	bzero ((char *)sc->rl_ldata.rl_tx_list,
+	    RL_DESC_COUNT(sc) * sizeof(struct rl_desc));
+	bzero ((char *)sc->rl_ldata.rl_tx_mbuf,
+	    RL_DESC_COUNT(sc) * sizeof(struct mbuf *));
 
 	bus_dmamap_sync(sc->rl_ldata.rl_tx_list_tag,
 	    sc->rl_ldata.rl_tx_list_map, BUS_DMASYNC_PREWRITE);
 	sc->rl_ldata.rl_tx_prodidx = 0;
 	sc->rl_ldata.rl_tx_considx = 0;
-	sc->rl_ldata.rl_tx_free = RL_TX_DESC_CNT;
+	sc->rl_ldata.rl_tx_free = RL_DESC_COUNT(sc);
 
 	return (0);
 }
@@ -1471,11 +1531,12 @@
 {
 	int			i;
 
-	bzero ((char *)sc->rl_ldata.rl_rx_list, RL_RX_LIST_SZ);
-	bzero ((char *)&sc->rl_ldata.rl_rx_mbuf,
-	    (RL_RX_DESC_CNT * sizeof(struct mbuf *)));
+	bzero ((char *)sc->rl_ldata.rl_rx_list,
+	    RL_DESC_COUNT(sc) * sizeof(struct rl_desc));
+	bzero ((char *)sc->rl_ldata.rl_rx_mbuf,
+	    RL_DESC_COUNT(sc) * sizeof(struct mbuf *));
 
-	for (i = 0; i < RL_RX_DESC_CNT; i++) {
+	for (i = 0; i < RL_DESC_COUNT(sc); i++) {
 		if (re_newbuf(sc, i, NULL) == ENOBUFS)
 			return (ENOBUFS);
 	}
@@ -1543,7 +1604,7 @@
 				sc->rl_tail = m;
 			}
 			re_newbuf(sc, i, NULL);
-			RL_DESC_INC(i);
+			RL_DESC_INC(sc,i);
 			continue;
 		}
 
@@ -1582,7 +1643,7 @@
 				sc->rl_head = sc->rl_tail = NULL;
 			}
 			re_newbuf(sc, i, m);
-			RL_DESC_INC(i);
+			RL_DESC_INC(sc,i);
 			continue;
 		}
 
@@ -1598,11 +1659,11 @@
 				sc->rl_head = sc->rl_tail = NULL;
 			}
 			re_newbuf(sc, i, m);
-			RL_DESC_INC(i);
+			RL_DESC_INC(sc,i);
 			continue;
 		}
 
-		RL_DESC_INC(i);
+		RL_DESC_INC(sc,i);
 
 		if (sc->rl_head != NULL) {
 			m->m_len = total_len % RE_RX_DESC_BUFLEN;
@@ -1718,7 +1779,7 @@
 				ifp->if_opackets++;
 		}
 		sc->rl_ldata.rl_tx_free++;
-		RL_DESC_INC(idx);
+		RL_DESC_INC(sc,idx);
 	}
 
 	/* No changes made to the TX ring, so no flush needed */
@@ -1735,7 +1796,7 @@
 	 * interrupt that will cause us to re-enter this routine.
 	 * This is done in case the transmitter has gone idle.
 	 */
-	if (sc->rl_ldata.rl_tx_free != RL_TX_DESC_CNT)
+	if (sc->rl_ldata.rl_tx_free != RL_DESC_COUNT(sc))
 		CSR_WRITE_4(sc, RL_TIMERCNT, 1);
 }
 
@@ -1901,42 +1962,22 @@
 	arg.sc = sc;
 	arg.rl_idx = *idx;
 	arg.rl_maxsegs = sc->rl_ldata.rl_tx_free;
-	if (arg.rl_maxsegs > 4)
-		arg.rl_maxsegs -= 4;
 	arg.rl_ring = sc->rl_ldata.rl_tx_list;
 
 	map = sc->rl_ldata.rl_tx_dmamap[*idx];
+
+	m_new = m_defrag(*m_head, M_DONTWAIT);
+	if (m_new != NULL)
+		*m_head = m_new;
+
 	error = bus_dmamap_load_mbuf(sc->rl_ldata.rl_mtag, map,
 	    *m_head, re_dma_map_desc, &arg, BUS_DMA_NOWAIT);
 
-	if (error && error != EFBIG) {
+	if (error) {
 		if_printf(sc->rl_ifp, "can't map mbuf (error %d)\n", error);
 		return (ENOBUFS);
 	}
 
-	/* Too many segments to map, coalesce into a single mbuf */
-
-	if (error || arg.rl_maxsegs == 0) {
-		m_new = m_defrag(*m_head, M_DONTWAIT);
-		if (m_new == NULL)
-			return (ENOBUFS);
-		else
-			*m_head = m_new;
-
-		arg.sc = sc;
-		arg.rl_idx = *idx;
-		arg.rl_maxsegs = sc->rl_ldata.rl_tx_free;
-		arg.rl_ring = sc->rl_ldata.rl_tx_list;
-
-		error = bus_dmamap_load_mbuf(sc->rl_ldata.rl_mtag, map,
-		    *m_head, re_dma_map_desc, &arg, BUS_DMA_NOWAIT);
-		if (error) {
-			if_printf(sc->rl_ifp, "can't map mbuf (error %d)\n",
-			    error);
-			return (EFBIG);
-		}
-	}
-
 	/*
 	 * Insure that the map for this transmission
 	 * is placed at the array index of the last descriptor
@@ -1968,7 +2009,7 @@
 		sc->rl_ldata.rl_tx_list[*idx].rl_cmdstat |=
 		    htole32(RL_TDESC_CMD_OWN);
 
-	RL_DESC_INC(arg.rl_idx);
+	RL_DESC_INC(sc,arg.rl_idx);
 	*idx = arg.rl_idx;
 
 	return (0);
@@ -2405,7 +2446,7 @@
 
 	/* Free the TX list buffers. */
 
-	for (i = 0; i < RL_TX_DESC_CNT; i++) {
+	for (i = 0; i < RL_DESC_COUNT(sc); i++) {
 		if (sc->rl_ldata.rl_tx_mbuf[i] != NULL) {
 			bus_dmamap_unload(sc->rl_ldata.rl_mtag,
 			    sc->rl_ldata.rl_tx_dmamap[i]);
@@ -2416,7 +2457,7 @@
 
 	/* Free the RX list buffers. */
 
-	for (i = 0; i < RL_RX_DESC_CNT; i++) {
+	for (i = 0; i < RL_DESC_COUNT(sc); i++) {
 		if (sc->rl_ldata.rl_rx_mbuf[i] != NULL) {
 			bus_dmamap_unload(sc->rl_ldata.rl_mtag,
 			    sc->rl_ldata.rl_rx_dmamap[i]);

--=-bBWu23haOdgH96FR+ng9--




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1129216390.8681.6.camel>