Greetings,

I tried to write mclgeti support for epic(4). Unfortunately, I can't 
blast it enough. I'd much appreciate if someone can a more in depth torture.

Feedback and advice would be very helpful.

Thanks,
Logan

Index: src/sys/dev/ic/smc83c170.c
===================================================================
RCS file: /cvs/src/sys/dev/ic/smc83c170.c,v
retrieving revision 1.14
diff -u -p -r1.14 smc83c170.c
--- src/sys/dev/ic/smc83c170.c  10 Aug 2009 20:29:54 -0000      1.14
+++ src/sys/dev/ic/smc83c170.c  12 Dec 2010 18:00:07 -0000
@@ -83,6 +83,7 @@ void  epic_stop(struct ifnet *, int);
 
 void   epic_reset(struct epic_softc *);
 void   epic_rxdrain(struct epic_softc *);
+void   epic_fill_rx_ring(struct epic_softc *);
 int    epic_add_rxbuf(struct epic_softc *, int);
 void   epic_read_eeprom(struct epic_softc *, int, int, u_int16_t *);
 void   epic_set_mchash(struct epic_softc *);
@@ -286,7 +287,7 @@ epic_attach(struct epic_softc *sc, const
        ifp->if_watchdog = epic_watchdog;
        IFQ_SET_MAXLEN(&ifp->if_snd, EPIC_NTXDESC - 1);
        IFQ_SET_READY(&ifp->if_snd);
-
+       m_clsetwms(ifp, MCLBYTES, 2, EPIC_NRXDESC - 1);
        ifp->if_capabilities = IFCAP_VLAN_MTU;
 
        /*
@@ -621,7 +622,7 @@ epic_intr(void *arg)
         * Check for receive interrupts.
         */
        if (intstat & (INTSTAT_RCC | INTSTAT_RXE | INTSTAT_RQE)) {
-               for (i = sc->sc_rxptr;; i = EPIC_NEXTRX(i)) {
+               for (i = sc->sc_rx_cons; sc->sc_rx_cnt > 0; i = EPIC_NEXTRX(i)) 
{
                        rxd = EPIC_CDRX(sc, i);
                        ds = EPIC_DSRX(sc, i);
 
@@ -637,6 +638,13 @@ epic_intr(void *arg)
                                break;
                        }
 
+                       bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0,          
+                       ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
+                       bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap);
+
+                       m = ds->ds_mbuf;
+                       ds->ds_mbuf = NULL;
+                       sc->sc_rx_cnt--;
                        /*
                         * Make sure the packet arrived intact.  If an error
                         * occurred, update stats and reset the descriptor.
@@ -651,13 +659,10 @@ epic_intr(void *arg)
                                        printf("%s: alignment error\n",
                                            sc->sc_dev.dv_xname);
                                ifp->if_ierrors++;
-                               EPIC_INIT_RXDESC(sc, i);
+                               m_freem(m);
                                continue;
                        }
 
-                       bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0,
-                           ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
-
                        /*
                         * The EPIC includes the CRC with every packet;
                         * trim it.
@@ -669,51 +674,16 @@ epic_intr(void *arg)
                                 * Runt packet; drop it now.
                                 */
                                ifp->if_ierrors++;
-                               EPIC_INIT_RXDESC(sc, i);
+                               m_freem(m);
                                bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0,
                                    ds->ds_dmamap->dm_mapsize,
                                    BUS_DMASYNC_PREREAD);
                                continue;
                        }
 
-                       /*
-                        * If the packet is small enough to fit in a
-                        * single header mbuf, allocate one and copy
-                        * the data into it.  This greatly reduces
-                        * memory consumption when we receive lots
-                        * of small packets.
-                        *
-                        * Otherwise, we add a new buffer to the receive
-                        * chain.  If this fails, we drop the packet and
-                        * recycle the old buffer.
-                        */
-                       if (epic_copy_small != 0 && len <= MHLEN) {
-                               MGETHDR(m, M_DONTWAIT, MT_DATA);
-                               if (m == NULL)
-                                       goto dropit;
-                               memcpy(mtod(m, caddr_t),
-                                   mtod(ds->ds_mbuf, caddr_t), len);
-                               EPIC_INIT_RXDESC(sc, i);
-                               bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0,
-                                   ds->ds_dmamap->dm_mapsize,
-                                   BUS_DMASYNC_PREREAD);
-                       } else {
-                               m = ds->ds_mbuf;
-                               if (epic_add_rxbuf(sc, i) != 0) {
- dropit:
-                                       ifp->if_ierrors++;
-                                       EPIC_INIT_RXDESC(sc, i);
-                                       bus_dmamap_sync(sc->sc_dmat,
-                                           ds->ds_dmamap, 0,
-                                           ds->ds_dmamap->dm_mapsize,
-                                           BUS_DMASYNC_PREREAD);
-                                       continue;
-                               }
-                       }
-
                        m->m_pkthdr.rcvif = ifp;
                        m->m_pkthdr.len = m->m_len = len;
-
+                       m->m_data += 2;
 #if NBPFILTER > 0
                        /*
                         * Pass this up to any BPF listeners, but only
@@ -729,20 +699,16 @@ epic_intr(void *arg)
                }
 
                /* Update the receive pointer. */
-               sc->sc_rxptr = i;
-
+               sc->sc_rx_cons = i;
+               epic_fill_rx_ring(sc);
                /*
                 * Check for receive queue underflow.
                 */
                if (intstat & INTSTAT_RQE) {
-                       printf("%s: receiver queue empty\n",
-                           sc->sc_dev.dv_xname);
                        /*
                         * Ring is already built; just restart the
                         * receiver.
                         */
-                       bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_PRCDAR,
-                           EPIC_CDRXADDR(sc, sc->sc_rxptr));
                        bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_COMMAND,
                            COMMAND_RXQUEUED | COMMAND_START_RX);
                }
@@ -908,9 +874,8 @@ epic_init(struct ifnet *ifp)
        bus_space_tag_t st = sc->sc_st;
        bus_space_handle_t sh = sc->sc_sh;
        struct epic_txdesc *txd;
-       struct epic_descsoft *ds;
        u_int32_t genctl, reg0;
-       int i, error = 0;
+       int i;
 
        /*
         * Cancel any pending I/O.
@@ -998,24 +963,12 @@ epic_init(struct ifnet *ifp)
         * Initialize the receive descriptor ring.
         */
        for (i = 0; i < EPIC_NRXDESC; i++) {
-               ds = EPIC_DSRX(sc, i);
-               if (ds->ds_mbuf == NULL) {
-                       if ((error = epic_add_rxbuf(sc, i)) != 0) {
-                               printf("%s: unable to allocate or map rx "
-                                   "buffer %d error = %d\n",
-                                   sc->sc_dev.dv_xname, i, error);
-                               /*
-                                * XXX Should attempt to run with fewer receive
-                                * XXX buffers instead of just failing.
-                                */
-                               epic_rxdrain(sc);
-                               goto out;
-                       }
-               } else
-                       EPIC_INIT_RXDESC(sc, i);
+               sc->sc_control_data->ecd_rxdescs[i].er_bufaddr = 0;
+               sc->sc_control_data->ecd_rxdescs[i].er_control = 0;
+               sc->sc_control_data->ecd_rxdescs[i].er_rxstatus = 0;
+               sc->sc_control_data->ecd_rxdescs[i].er_nextdesc = 0; 
        }
-       sc->sc_rxptr = 0;
-
+       epic_fill_rx_ring(sc);
        /*
         * Initialize the interrupt mask and enable interrupts.
         */
@@ -1028,7 +981,7 @@ epic_init(struct ifnet *ifp)
        bus_space_write_4(st, sh, EPIC_PTCDAR,
            EPIC_CDTXADDR(sc, EPIC_NEXTTX(sc->sc_txlast)));
        bus_space_write_4(st, sh, EPIC_PRCDAR,
-           EPIC_CDRXADDR(sc, sc->sc_rxptr));
+           EPIC_CDRXADDR(sc, sc->sc_rx_prod));
 
        /*
         * Set the EPIC in motion.
@@ -1052,10 +1005,7 @@ epic_init(struct ifnet *ifp)
         */
        epic_start(ifp);
 
- out:
-       if (error)
-               printf("%s: interface not running\n", sc->sc_dev.dv_xname);
-       return (error);
+       return (0);
 }
 
 /*
@@ -1075,6 +1025,7 @@ epic_rxdrain(struct epic_softc *sc)
                        ds->ds_mbuf = NULL;
                }
        }
+       sc->sc_rx_prod = sc->sc_rx_cons = sc->sc_rx_cnt = 0;
 }
 
 /*
@@ -1213,6 +1164,15 @@ epic_read_eeprom(struct epic_softc *sc, 
 #undef EEPROM_WAIT_READY
 }
 
+void 
+epic_fill_rx_ring(struct epic_softc *sc)
+{
+       while(sc->sc_rx_cnt < EPIC_NRXDESC) {
+               if(epic_add_rxbuf(sc, sc->sc_rx_prod))
+                       break;
+       }
+}
+
 /*
  * Add a receive buffer to the indicated descriptor.
  */
@@ -1223,23 +1183,14 @@ epic_add_rxbuf(struct epic_softc *sc, in
        struct mbuf *m;
        int error;
 
-       MGETHDR(m, M_DONTWAIT, MT_DATA);
-       if (m == NULL)
+       m = MCLGETI(NULL, M_DONTWAIT, &sc->sc_arpcom.ac_if, MCLBYTES);
+       if (!m)
                return (ENOBUFS);
-
-       MCLGET(m, M_DONTWAIT);
-       if ((m->m_flags & M_EXT) == 0) {
-               m_freem(m);
-               return (ENOBUFS);
-       }
-
-       if (ds->ds_mbuf != NULL)
-               bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap);
+       m->m_len = m->m_pkthdr.len = MCLBYTES;
 
        ds->ds_mbuf = m;
 
-       error = bus_dmamap_load(sc->sc_dmat, ds->ds_dmamap,
-           m->m_ext.ext_buf, m->m_ext.ext_size, NULL,
+       error = bus_dmamap_load_mbuf(sc->sc_dmat, ds->ds_dmamap, m,
            BUS_DMA_READ|BUS_DMA_NOWAIT);
        if (error) {
                printf("%s: can't load rx DMA map %d, error = %d\n",
@@ -1251,6 +1202,8 @@ epic_add_rxbuf(struct epic_softc *sc, in
            ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
 
        EPIC_INIT_RXDESC(sc, idx);
+       sc->sc_rx_prod = EPIC_NEXTRX(sc->sc_rx_prod);
+       sc->sc_rx_cnt++;
 
        return (0);
 }
Index: src/sys/dev/ic/smc83c170var.h
===================================================================
RCS file: /cvs/src/sys/dev/ic/smc83c170var.h,v
retrieving revision 1.3
diff -u -p -r1.3 smc83c170var.h
--- src/sys/dev/ic/smc83c170var.h       10 Aug 2009 20:29:54 -0000      1.3
+++ src/sys/dev/ic/smc83c170var.h       12 Dec 2010 18:00:07 -0000
@@ -128,7 +128,9 @@ struct epic_softc {
        int     sc_txdirty;             /* first dirty TX descriptor */
        int     sc_txlast;              /* last used TX descriptor */
 
-       int     sc_rxptr;               /* next ready RX descriptor */
+       int     sc_rx_cnt;
+       int     sc_rx_prod;
+       int     sc_rx_cons;
 
        u_int   sc_serinst;             /* ifmedia instance for serial mode */
 };
@@ -167,7 +169,6 @@ do {                                                        
                \
         * so that the payload after the Ethernet header is aligned     \
         * to a 4 byte boundary.                                        \
         */                                                             \
-       __m->m_data = __m->m_ext.ext_buf + 2;                           \
        __rxd->er_bufaddr = __ds->ds_dmamap->dm_segs[0].ds_addr + 2;    \
        __rxd->er_control = RXCTL_BUFLENGTH(__m->m_ext.ext_size - 2);   \
        __rxd->er_rxstatus = ER_RXSTAT_OWNER;                           \

Reply via email to