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