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


Index: xl.c
===================================================================
RCS file: /cvs/src/sys/dev/ic/xl.c,v
retrieving revision 1.88
diff -u -p -r1.88 xl.c
--- xl.c        22 Dec 2009 21:10:25 -0000      1.88
+++ xl.c        24 Dec 2009 07:57:00 -0000
@@ -1614,23 +1614,25 @@ xl_encap(struct xl_softc *sc, struct xl_
 
        map = sc->sc_tx_sparemap;
 
-reload:
        error = bus_dmamap_load_mbuf(sc->sc_dmat, map,
            m_head, BUS_DMA_NOWAIT);
-
-       if (error && error != EFBIG) {
-               m_freem(m_head);
-               return (1);
+       if (error != 0 && error != EFBIG)
+               goto drop;
+       if (error != 0) {
+               if (m_defrag(m_head, M_DONTWAIT))
+                       goto drop;
+               error = bus_dmamap_load_mbuf(sc->sc_dmat, map,
+                   m_head, BUS_DMA_NOWAIT);
+               if (error != 0)
+                       goto drop;
        }
 
        /*
         * Start packing the mbufs in this chain into
-        * the fragment pointers. Stop when we run out
-        * of fragments or hit the end of the mbuf chain.
+        * the fragment pointers. Stop when we hit the
+        * end of the mbuf chain.
         */
        for (frag = 0, total_len = 0; frag < map->dm_nsegs; frag++) {
-               if (frag == XL_MAXFRAGS)
-                       break;
                total_len += map->dm_segs[frag].ds_len;
                c->xl_ptr->xl_frag[frag].xl_addr =
                    htole32(map->dm_segs[frag].ds_addr);
@@ -1638,38 +1640,6 @@ reload:
                    htole32(map->dm_segs[frag].ds_len);
        }
 
-       /*
-        * Handle special case: we used up all 63 fragments,
-        * but we have more mbufs left in the chain. Copy the
-        * data into an mbuf cluster. Note that we don't
-        * bother clearing the values in the other fragment
-        * pointers/counters; it wouldn't gain us anything,
-        * and would waste cycles.
-        */
-       if (error) {
-               struct mbuf     *m_new = NULL;
-
-               MGETHDR(m_new, M_DONTWAIT, MT_DATA);
-               if (m_new == NULL) {
-                       m_freem(m_head);
-                       return (1);
-               }
-               if (m_head->m_pkthdr.len > MHLEN) {
-                       MCLGET(m_new, M_DONTWAIT);
-                       if (!(m_new->m_flags & M_EXT)) {
-                               m_freem(m_new);
-                               m_freem(m_head);
-                               return (1);
-                       }
-               }
-               m_copydata(m_head, 0, m_head->m_pkthdr.len,     
-                   mtod(m_new, caddr_t));
-               m_new->m_pkthdr.len = m_new->m_len = m_head->m_pkthdr.len;
-               m_freem(m_head);
-               m_head = m_new;
-               goto reload;
-       }
-
        bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
            BUS_DMASYNC_PREWRITE);
 
@@ -1708,6 +1678,10 @@ reload:
            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 
        return (0);
+
+ drop:
+       m_freem(m_head);
+       return (1);
 }
 
 /*

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

Reply via email to