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/