Latest if_bfe - I think it works!

Mike Silbersack silby at silby.com
Wed May 3 07:38:34 UTC 2006


Ok, I got it working with an artificial 128MB limit.  I had to fix two 
major issues:

1.  It was requiring more bounce buffers than busdma was prepared to give 
it, so I reduced the size of the rings.
2.  It was leaking bounce buffers whenever you transmitted a 
multi-fragment buffer, which pretty much means any non-ping packet.

and scottl fixed #3 with rev 1.77 of busdma_machdep.c

3.  busdma wasn't telling us when we ran out of bounce buffers.

However, now that #1 and #2 are fixed, #3 shouldn't come into play ever, 
as far as I can tell.

I'm writing this e-mail via ssh into pine on the machine which has the 
artificial 128MB limit set, looking at hw.busdma sysctl I can see that 
it's bouncing pages all over the place, so I can say that it seems to be 
good to me.  Please test.

Thanks,

Mike "Silby" Silbersack
-------------- next part --------------
diff -u -r /usr/src/sys.old/dev/bfe/if_bfe.c /usr/src/sys/dev/bfe/if_bfe.c
--- /usr/src/sys.old/dev/bfe/if_bfe.c	Mon May  1 00:31:18 2006
+++ /usr/src/sys/dev/bfe/if_bfe.c	Wed May  3 02:24:35 2006
@@ -297,7 +298,7 @@
 	bzero(sc->bfe_rx_list, BFE_RX_LIST_SIZE);
 	error = bus_dmamap_load(sc->bfe_rx_tag, sc->bfe_rx_map,
 			sc->bfe_rx_list, sizeof(struct bfe_desc),
-			bfe_dma_map, &sc->bfe_rx_dma, 0);
+			bfe_dma_map, &sc->bfe_rx_dma, BUS_DMA_NOWAIT);
 
 	if(error)
 		return (ENOMEM);
@@ -312,7 +313,7 @@
 
 	error = bus_dmamap_load(sc->bfe_tx_tag, sc->bfe_tx_map,
 			sc->bfe_tx_list, sizeof(struct bfe_desc),
-			bfe_dma_map, &sc->bfe_tx_dma, 0);
+			bfe_dma_map, &sc->bfe_tx_dma, BUS_DMA_NOWAIT);
 	if(error)
 		return (ENOMEM);
 
@@ -574,6 +575,7 @@
 	struct bfe_desc *d;
 	struct bfe_data *r;
 	u_int32_t ctrl;
+	int error;
 
 	if ((c < 0) || (c >= BFE_RX_LIST_CNT))
 		return (EINVAL);
@@ -595,8 +597,10 @@
 	sc->bfe_rx_cnt = c;
 	d = &sc->bfe_rx_list[c];
 	r = &sc->bfe_rx_ring[c];
-	bus_dmamap_load(sc->bfe_tag, r->bfe_map, mtod(m, void *),
-			MCLBYTES, bfe_dma_map_desc, d, 0);
+	error = bus_dmamap_load(sc->bfe_tag, r->bfe_map, mtod(m, void *),
+			MCLBYTES, bfe_dma_map_desc, d, BUS_DMA_NOWAIT);
+	if (error)
+		printf("Error I can't handle!!!\n");
 	bus_dmamap_sync(sc->bfe_tag, r->bfe_map, BUS_DMASYNC_PREWRITE);
 
 	ctrl = ETHER_MAX_LEN + 32;
@@ -1102,8 +1106,8 @@
 			ifp->if_opackets++;
 			m_freem(r->bfe_mbuf);
 			r->bfe_mbuf = NULL;
-			bus_dmamap_unload(sc->bfe_tag, r->bfe_map);
 		}
+		bus_dmamap_unload(sc->bfe_tag, r->bfe_map);
 		sc->bfe_tx_cnt--;
 		BFE_INC(i, BFE_TX_LIST_CNT);
 	}
@@ -1241,13 +1245,14 @@
 }
 
 static int
-bfe_encap(struct bfe_softc *sc, struct mbuf *m_head, u_int32_t *txidx)
+bfe_encap(struct bfe_softc *sc, struct mbuf **m_head, u_int32_t *txidx)
 {
 	struct bfe_desc *d = NULL;
 	struct bfe_data *r = NULL;
 	struct mbuf	*m;
 	u_int32_t	   frag, cur, cnt = 0;
 	int chainlen = 0;
+	int error;
 
 	if(BFE_TX_LIST_CNT - sc->bfe_tx_cnt < 2)
 		return (ENOBUFS);
@@ -1258,16 +1263,16 @@
 	 * by all packets, we'll m_defrag long chains so that they
 	 * do not use up the entire list, even if they would fit.
 	 */
-	for(m = m_head; m != NULL; m = m->m_next)
+	for(m = *m_head; m != NULL; m = m->m_next) {
 		chainlen++;
-
+	}
 
 	if ((chainlen > BFE_TX_LIST_CNT / 4) ||
 			((BFE_TX_LIST_CNT - (chainlen + sc->bfe_tx_cnt)) < 2)) {
-		m = m_defrag(m_head, M_DONTWAIT);
+		m = m_defrag(*m_head, M_DONTWAIT);
 		if (m == NULL)
 			return (ENOBUFS);
-		m_head = m;
+		*m_head = m;
 	}
 
 	/*
@@ -1275,11 +1280,10 @@
 	 * the fragment pointers. Stop when we run out
 	 * of fragments or hit the end of the mbuf chain.
 	 */
-	m = m_head;
 	cur = frag = *txidx;
 	cnt = 0;
 
-	for(m = m_head; m != NULL; m = m->m_next) {
+	for(m = *m_head; m != NULL; m = m->m_next) {
 		if(m->m_len != 0) {
 			if((BFE_TX_LIST_CNT - (sc->bfe_tx_cnt + cnt)) < 2)
 				return (ENOBUFS);
@@ -1299,9 +1303,13 @@
 				 */
 				d->bfe_ctrl |= BFE_DESC_EOT;
 
-			bus_dmamap_load(sc->bfe_tag,
+			error = bus_dmamap_load(sc->bfe_tag,
 			    r->bfe_map, mtod(m, void*), m->m_len,
-			    bfe_dma_map_desc, d, 0);
+			    bfe_dma_map_desc, d, BUS_DMA_NOWAIT);
+			if (error) {
+				printf("dmamap_load error, ENOBUFS\n");
+				return (ENOBUFS);
+			}
 			bus_dmamap_sync(sc->bfe_tag, r->bfe_map,
 			    BUS_DMASYNC_PREWRITE);
 
@@ -1315,7 +1323,7 @@
 		return (ENOBUFS);
 
 	sc->bfe_tx_list[frag].bfe_ctrl |= BFE_DESC_EOF;
-	sc->bfe_tx_ring[frag].bfe_mbuf = m_head;
+	sc->bfe_tx_ring[frag].bfe_mbuf = *m_head;
 	bus_dmamap_sync(sc->bfe_tx_tag, sc->bfe_tx_map, BUS_DMASYNC_PREWRITE);
 
 	*txidx = cur;
@@ -1368,7 +1376,7 @@
 		 * Pack the data into the tx ring.  If we dont have
 		 * enough room, let the chip drain the ring.
 		 */
-		if(bfe_encap(sc, m_head, &idx)) {
+		if(bfe_encap(sc, &m_head, &idx)) {
 			IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
 			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
 			break;
Only in /usr/src/sys/dev/bfe: if_bfe.c.good
Only in /usr/src/sys/dev/bfe: if_bfe.c.orig
Only in /usr/src/sys/dev/bfe: if_bfe.c.wip
Only in /usr/src/sys/dev/bfe: if_bfe.c.wip2
diff -u -r /usr/src/sys.old/dev/bfe/if_bfereg.h /usr/src/sys/dev/bfe/if_bfereg.h
--- /usr/src/sys.old/dev/bfe/if_bfereg.h	Thu Apr 27 01:09:07 2006
+++ /usr/src/sys/dev/bfe/if_bfereg.h	Wed May  3 02:16:42 2006
@@ -427,8 +427,8 @@
 #define BFE_RX_RING_SIZE        512
 #define BFE_TX_RING_SIZE        512
 #define BFE_LINK_DOWN           5
-#define BFE_TX_LIST_CNT         511
-#define BFE_RX_LIST_CNT         511
+#define BFE_TX_LIST_CNT         128
+#define BFE_RX_LIST_CNT         128
 #define BFE_TX_LIST_SIZE        BFE_TX_LIST_CNT * sizeof(struct bfe_desc)
 #define BFE_RX_LIST_SIZE        BFE_RX_LIST_CNT * sizeof(struct bfe_desc)
 #define BFE_RX_OFFSET           30


More information about the freebsd-mobile mailing list