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.