Also tested this patch on my old i386. xl0 at pci2 dev 1 function 0 "3Com 3c905B 100Base-TX" rev 0x30: apic 2 int 17 (irq 12), address 00:50:04:44:dc:5c exphy0 at xl0 phy 24: 3Com internal media interface
Same tests (ftp, nfs, ssh, ipv4 and ipv6), no regressions. Paul 'WEiRD' de Weerd On Thu, Dec 24, 2009 at 03:08:54AM -0500, Brad wrote: | 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. | -- >++++++++[<++++++++++>-]<+++++++.>+++[<------>-]<.>+++[<+ +++++++++++>-]<.>++[<------------>-]<+.--------------.[-] http://www.weirdnet.nl/