Hi, with further encouragement, I decided to give tl(4) a try.
It's a very interesting ethernet chip, and even under heavy tcpbench
the mbuf usage is at most 6. As usual, feedback and comments are welcomed.
//Logan
C-x-C-c
Index: src/sys/dev/pci/if_tl.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_tl.c,v
retrieving revision 1.50
diff -u -p -r1.50 if_tl.c
--- src/sys/dev/pci/if_tl.c 19 May 2010 15:27:35 -0000 1.50
+++ src/sys/dev/pci/if_tl.c 14 Dec 2010 19:15:28 -0000
@@ -252,8 +252,8 @@ int tl_intvec_rxeof(void *, u_int32_t);
int tl_intvec_adchk(void *, u_int32_t);
int tl_intvec_netsts(void *, u_int32_t);
-int tl_newbuf(struct tl_softc *,
- struct tl_chain_onefrag *);
+int tl_newbuf(struct tl_softc *, struct tl_chain_onefrag *);
+void tl_fill_rx_ring(struct tl_softc *);
void tl_stats_update(void *);
int tl_encap(struct tl_softc *, struct tl_chain *,
struct mbuf *);
@@ -1034,8 +1034,6 @@ int tl_list_rx_init(sc)
for (i = 0; i < TL_RX_LIST_CNT; i++) {
cd->tl_rx_chain[i].tl_ptr =
(struct tl_list_onefrag *)&ld->tl_rx_list[i];
- if (tl_newbuf(sc, &cd->tl_rx_chain[i]) == ENOBUFS)
- return(ENOBUFS);
if (i == (TL_RX_LIST_CNT - 1)) {
cd->tl_rx_chain[i].tl_next = NULL;
ld->tl_rx_list[i].tlist_fptr = 0;
@@ -1047,34 +1045,45 @@ int tl_list_rx_init(sc)
}
cd->tl_rx_head = &cd->tl_rx_chain[0];
+ cd->tl_rx_cons = &cd->tl_rx_chain[0];
cd->tl_rx_tail = &cd->tl_rx_chain[TL_RX_LIST_CNT - 1];
-
+ cd->tl_rx_cnt = 0;
+ tl_fill_rx_ring(sc);
return(0);
}
+void tl_fill_rx_ring(sc)
+ struct tl_softc *sc;
+{
+ struct tl_list_data *ld;
+ struct tl_chain_data *cd;
+
+ cd = &sc->tl_cdata;
+ ld = sc->tl_ldata;
+
+ while (cd->tl_rx_cnt < TL_RX_LIST_CNT) {
+ if(tl_newbuf(sc, cd->tl_rx_head) == ENOBUFS)
+ break;
+ cd->tl_rx_head = cd->tl_rx_head->tl_next;
+ cd->tl_rx_cnt++;
+ }
+}
+
int tl_newbuf(sc, c)
struct tl_softc *sc;
struct tl_chain_onefrag *c;
{
struct mbuf *m_new = NULL;
- MGETHDR(m_new, M_DONTWAIT, MT_DATA);
- if (m_new == NULL) {
+ m_new = MCLGETI(NULL, M_DONTWAIT, &sc->arpcom.ac_if, MCLBYTES);
+ if (!m_new)
return(ENOBUFS);
- }
-
- MCLGET(m_new, M_DONTWAIT);
- if (!(m_new->m_flags & M_EXT)) {
- m_freem(m_new);
- return(ENOBUFS);
- }
#ifdef __alpha__
m_new->m_data += 2;
#endif
c->tl_mbuf = m_new;
- c->tl_next = NULL;
c->tl_ptr->tlist_frsize = MCLBYTES;
c->tl_ptr->tlist_fptr = 0;
c->tl_ptr->tl_frag.tlist_dadr = VTOPHYS(mtod(m_new, caddr_t));
@@ -1120,23 +1129,17 @@ int tl_intvec_rxeof(xsc, type)
sc = xsc;
ifp = &sc->arpcom.ac_if;
- while(sc->tl_cdata.tl_rx_head != NULL) {
- cur_rx = sc->tl_cdata.tl_rx_head;
+ while(sc->tl_cdata.tl_rx_cnt > 0) {
+ cur_rx = sc->tl_cdata.tl_rx_cons;
if (!(cur_rx->tl_ptr->tlist_cstat & TL_CSTAT_FRAMECMP))
break;
r++;
- sc->tl_cdata.tl_rx_head = cur_rx->tl_next;
+ sc->tl_cdata.tl_rx_cons = cur_rx->tl_next;
m = cur_rx->tl_mbuf;
+ cur_rx->tl_mbuf = NULL;
+ sc->tl_cdata.tl_rx_cnt--;
total_len = cur_rx->tl_ptr->tlist_frsize;
- if (tl_newbuf(sc, cur_rx) == ENOBUFS) {
- ifp->if_ierrors++;
- cur_rx->tl_ptr->tlist_frsize = MCLBYTES;
- cur_rx->tl_ptr->tlist_cstat = TL_CSTAT_READY;
- cur_rx->tl_ptr->tl_frag.tlist_dcnt = MCLBYTES;
- continue;
- }
-
sc->tl_cdata.tl_rx_tail->tl_ptr->tlist_fptr =
VTOPHYS(cur_rx->tl_ptr);
sc->tl_cdata.tl_rx_tail->tl_next = cur_rx;
@@ -1175,7 +1178,7 @@ int tl_intvec_rxeof(xsc, type)
/* pass it on. */
ether_input_mbuf(ifp, m);
}
-
+ tl_fill_rx_ring(sc);
return(r);
}
@@ -1201,9 +1204,7 @@ int tl_intvec_rxeoc(xsc, type)
r = tl_intvec_rxeof(xsc, type);
CMD_PUT(sc, TL_CMD_ACK | r | (type & ~(0x00100000)));
r = 1;
- cd->tl_rx_head = &cd->tl_rx_chain[0];
- cd->tl_rx_tail = &cd->tl_rx_chain[TL_RX_LIST_CNT - 1];
- CSR_WRITE_4(sc, TL_CH_PARM, VTOPHYS(sc->tl_cdata.tl_rx_head->tl_ptr));
+ CSR_WRITE_4(sc, TL_CH_PARM, VTOPHYS(sc->tl_cdata.tl_rx_cons->tl_ptr));
r |= (TL_CMD_GO|TL_CMD_RT);
return(r);
}
@@ -2130,6 +2131,7 @@ tl_attach(parent, self, aux)
ifp->if_baudrate = 10000000;
IFQ_SET_MAXLEN(&ifp->if_snd, TL_TX_LIST_CNT - 1);
IFQ_SET_READY(&ifp->if_snd);
+ m_clsetwms(ifp, MCLBYTES, 2, TL_RX_LIST_CNT - 1);
bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
/*
Index: src/sys/dev/pci/if_tlreg.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_tlreg.h,v
retrieving revision 1.9
diff -u -p -r1.9 if_tlreg.h
--- src/sys/dev/pci/if_tlreg.h 17 Dec 2005 07:31:27 -0000 1.9
+++ src/sys/dev/pci/if_tlreg.h 14 Dec 2010 19:15:28 -0000
@@ -104,6 +104,8 @@ struct tl_chain_data {
struct tl_chain_onefrag *tl_rx_head;
struct tl_chain_onefrag *tl_rx_tail;
+ struct tl_chain_onefrag *tl_rx_cons;
+ int tl_rx_cnt;
struct tl_chain *tl_tx_head;
struct tl_chain *tl_tx_tail;