The following diff replaces the hand rolled code to deal with
really long mbuf chains with the use of m_defrag().


Index: if_pcn.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_pcn.c,v
retrieving revision 1.22
diff -u -p -r1.22 if_pcn.c
--- if_pcn.c    13 Aug 2009 14:24:47 -0000      1.22
+++ if_pcn.c    24 Dec 2009 20:12:39 -0000
@@ -851,7 +851,7 @@ void
 pcn_start(struct ifnet *ifp)
 {
        struct pcn_softc *sc = ifp->if_softc;
-       struct mbuf *m0, *m;
+       struct mbuf *m0;
        struct pcn_txsoft *txs;
        bus_dmamap_t dmamap;
        int error, nexttx, lasttx = -1, ofree, seg;
@@ -875,7 +875,6 @@ pcn_start(struct ifnet *ifp)
                IFQ_POLL(&ifp->if_snd, m0);
                if (m0 == NULL)
                        break;
-               m = NULL;
 
                /* Get a work queue entry. */
                if (sc->sc_txsfree == 0)
@@ -890,23 +889,16 @@ pcn_start(struct ifnet *ifp)
                 * were short on resources.  In this case, we'll copy
                 * and try again.
                 */
-               if (bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0,
-                   BUS_DMA_WRITE|BUS_DMA_NOWAIT) != 0) {
-                       MGETHDR(m, M_DONTWAIT, MT_DATA);
-                       if (m == NULL)
+               error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0,
+                   BUS_DMA_WRITE|BUS_DMA_NOWAIT);
+               if (error != 0 && error != EFBIG)
+                       break;
+               if (error != 0) {
+                       if (m_defrag(m0, M_DONTWAIT))
                                break;
-                       if (m0->m_pkthdr.len > MHLEN) {
-                               MCLGET(m, M_DONTWAIT);
-                               if ((m->m_flags & M_EXT) == 0) {
-                                       m_freem(m);
-                                       break;
-                               }
-                       }
-                       m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, caddr_t));
-                       m->m_pkthdr.len = m->m_len = m0->m_pkthdr.len;
                        error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap,
-                           m, BUS_DMA_WRITE|BUS_DMA_NOWAIT);
-                       if (error)
+                           m0, BUS_DMA_WRITE|BUS_DMA_NOWAIT);
+                       if (error != 0)
                                break;
                }
 
@@ -929,20 +921,13 @@ pcn_start(struct ifnet *ifp)
                         */
                        ifp->if_flags |= IFF_OACTIVE;
                        bus_dmamap_unload(sc->sc_dmat, dmamap);
-                       if (m != NULL)
-                               m_freem(m);
                        break;
                }
 
-               IFQ_DEQUEUE(&ifp->if_snd, m0);
-               if (m != NULL) {
-                       m_freem(m0);
-                       m0 = m;
-               }
-
                /*
                 * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET.
                 */
+               IFQ_DEQUEUE(&ifp->if_snd, m0);
 
                /* Sync the DMA map. */
                bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize,

-- 
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.

Reply via email to