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;

Reply via email to