Author: jfv
Date: Fri Apr  1 20:24:51 2011
New Revision: 220254
URL: http://svn.freebsd.org/changeset/base/220254

Log:
  Fix to an error condition case, when an mbuf chain
  get's defragged due to a mapping failure the header
  pointers will be invalidated and can result in a
  TSO or other failure down the line. So, when the
  remapping occurs force a retry thru the offload
  calculation code. Thanks to Andrew Boyer for discovering
  this and cooking up the fix!!

Modified:
  head/sys/dev/e1000/if_em.c

Modified: head/sys/dev/e1000/if_em.c
==============================================================================
--- head/sys/dev/e1000/if_em.c  Fri Apr  1 19:57:27 2011        (r220253)
+++ head/sys/dev/e1000/if_em.c  Fri Apr  1 20:24:51 2011        (r220254)
@@ -1761,8 +1761,9 @@ em_xmit(struct tx_ring *txr, struct mbuf
        u32                     txd_upper, txd_lower, txd_used, txd_saved;
        int                     ip_off, poff;
        int                     nsegs, i, j, first, last = 0;
-       int                     error, do_tso, tso_desc = 0;
+       int                     error, do_tso, tso_desc = 0, remap = 1;
 
+retry:
        m_head = *m_headp;
        txd_upper = txd_lower = txd_used = txd_saved = 0;
        do_tso = ((m_head->m_pkthdr.csum_flags & CSUM_TSO) != 0);
@@ -1900,7 +1901,7 @@ em_xmit(struct tx_ring *txr, struct mbuf
         * All other errors, in particular EINVAL, are fatal and prevent the
         * mbuf chain from ever going through.  Drop it and report error.
         */
-       if (error == EFBIG) {
+       if (error == EFBIG && remap) {
                struct mbuf *m;
 
                m = m_defrag(*m_headp, M_DONTWAIT);
@@ -1912,20 +1913,9 @@ em_xmit(struct tx_ring *txr, struct mbuf
                }
                *m_headp = m;
 
-               /* Try it again */
-               error = bus_dmamap_load_mbuf_sg(txr->txtag, map,
-                   *m_headp, segs, &nsegs, BUS_DMA_NOWAIT);
-
-               if (error == ENOMEM) {
-                       adapter->no_tx_dma_setup++;
-                       return (error);
-               } else if (error != 0) {
-                       adapter->no_tx_dma_setup++;
-                       m_freem(*m_headp);
-                       *m_headp = NULL;
-                       return (error);
-               }
-
+               /* Try it again, but only once */
+               remap = 0;
+               goto retry;
        } else if (error == ENOMEM) {
                adapter->no_tx_dma_setup++;
                return (error);
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to