From tejblum@walrus-t.yandex.ru  Sun Sep 18 19:25:43 2005
Return-Path: <tejblum@walrus-t.yandex.ru>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 9AC7216A41F
	for <FreeBSD-gnats-submit@freebsd.org>; Sun, 18 Sep 2005 19:25:43 +0000 (GMT)
	(envelope-from tejblum@walrus-t.yandex.ru)
Received: from walrus-t.yandex.ru (walrus-t.yandex.ru [213.180.206.233])
	by mx1.FreeBSD.org (Postfix) with ESMTP id CED7E43D45
	for <FreeBSD-gnats-submit@freebsd.org>; Sun, 18 Sep 2005 19:25:42 +0000 (GMT)
	(envelope-from tejblum@walrus-t.yandex.ru)
Received: from walrus-t.yandex.ru (localhost [127.0.0.1])
	by walrus-t.yandex.ru (8.13.3/8.13.3) with ESMTP id j8IJPamW046694
	for <FreeBSD-gnats-submit@freebsd.org>; Sun, 18 Sep 2005 23:25:36 +0400 (MSD)
	(envelope-from tejblum@walrus-t.yandex.ru)
Received: (from tejblum@localhost)
	by walrus-t.yandex.ru (8.13.3/8.13.3/Submit) id j8IJPZPe046693;
	Sun, 18 Sep 2005 23:25:35 +0400 (MSD)
	(envelope-from tejblum)
Message-Id: <200509181925.j8IJPZPe046693@walrus-t.yandex.ru>
Date: Sun, 18 Sep 2005 23:25:35 +0400 (MSD)
From: Dmitrij Tejblum <tejblum@yandex-team.ru>
Reply-To: Dmitrij Tejblum <tejblum@yandex-team.ru>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: [patch] if_em.c locks up while trying to send a highly fragmented packet
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         86306
>Category:       kern
>Synopsis:       [em] [patch] if_em.c locks up while trying to send a highly fragmented packet
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    yongari
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Sep 18 19:30:04 GMT 2005
>Closed-Date:    Mon Mar 26 20:38:43 GMT 2007
>Last-Modified:  Mon Mar 26 20:38:43 GMT 2007
>Originator:     Dmitrij Tejblum
>Release:        FreeBSD 5.4-STABLE i386
>Organization:
OOO Yandex
>Environment:

>Description:

When em_encap() tries to send a very long mbuf chain (i.e. more than
EM_MAX_SCATTER == 64 mbufs), bus_dmamap_load_mbuf_sg() may fail with EFBIG. 
Then em_encap() fail, the packet is not sent and left in the output queue, 
and thus no futher transmission is possible.

Some other driver handle similar condition with m_defrag(9) function
(which is intended for this purpose).

>How-To-Repeat:

This is more likely with jumbo frames enabled.

>Fix:


Index: if_em.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/em/if_em.c,v
retrieving revision 1.44.2.9
diff -u -r1.44.2.9 if_em.c
--- if_em.c	19 May 2005 08:23:06 -0000	1.44.2.9
+++ if_em.c	18 Sep 2005 18:43:15 -0000
@@ -631,13 +631,6 @@
 			break;
                 }
 
-		/* Send a copy of the frame to the BPF listener */
-#if __FreeBSD_version < 500000
-                if (ifp->if_bpf)
-                        bpf_mtap(ifp, m_head);
-#else
-		BPF_MTAP(ifp, m_head);
-#endif
         
                 /* Set timeout in case hardware has problems transmitting */
                 ifp->if_timer = EM_TX_TIMEOUT;
@@ -1221,10 +1214,37 @@
         }
         error = bus_dmamap_load_mbuf_sg(adapter->txtag, map, m_head, segs,
 					&nsegs, BUS_DMA_NOWAIT);
-        if (error != 0) {
+        if (error != 0 && error != EFBIG) {
+                printf("em%d: can't map mbuf (error %d)\n",
+                        adapter->unit, error);
                 adapter->no_tx_dma_setup++;
                 bus_dmamap_destroy(adapter->txtag, map);
-                return (error);
+                m_freem(m_head);
+                *m_headp = NULL;
+                return (0);
+        } else if (error == EFBIG) {
+                struct mbuf *mn;
+                mn = m_defrag(m_head, M_DONTWAIT);
+                if (mn == NULL) {
+                        printf("em%d: can't defrag mbuf\n", adapter->unit);
+                        bus_dmamap_destroy(adapter->txtag, map);
+                        m_freem(m_head);
+                        *m_headp = NULL;
+                        adapter->no_tx_dma_setup++;
+                        return (0);
+                }
+                m_head = mn;
+                error = bus_dmamap_load_mbuf_sg(adapter->txtag, map, m_head,
+                                                segs, &nsegs, BUS_DMA_NOWAIT);
+                if (error != 0) {
+                        printf("em%d: can't map mbuf2 (error %d)\n",
+                                adapter->unit, error);
+                        bus_dmamap_destroy(adapter->txtag, map);
+                        m_freem(m_head);
+                        *m_headp = NULL;
+                        adapter->no_tx_dma_setup++;
+                        return (0);
+                }
         }
         KASSERT(nsegs != 0, ("em_encap: empty packet"));
 
@@ -1390,6 +1410,13 @@
                 }
         }
 
+        /* Send a copy of the frame to the BPF listener */
+#if __FreeBSD_version < 500000
+        if (ifp->if_bpf)
+               bpf_mtap(ifp, m_head);
+#else
+        BPF_MTAP(ifp, m_head);
+#endif
         return(0);
 }
 
@@ -3258,7 +3285,8 @@
 	adapter->stats.mpc + adapter->stats.cexterr;
 
 	/* Tx Errors */
-	ifp->if_oerrors = adapter->stats.ecol + adapter->stats.latecol;
+	ifp->if_oerrors = adapter->stats.ecol + adapter->stats.latecol + 
+		adapter->no_tx_dma_setup + adapter->no_tx_map_avail;
 
 }
 


(When em_encap() return an error, futher transmission stops and the interface
is marked with OACTIVE. But OACTIVE mean that the *hardware* output queue is
full, and the code that clear OACTIVE assume so. Therefore I think that in 
case of mbuf or dmamap failure it is better to return 0 from em_encap()).

>Release-Note:
>Audit-Trail:

From: Ruslan Ermilov <ru@freebsd.org>
To: Dmitrij Tejblum <tejblum@yandex-team.ru>
Cc: FreeBSD-gnats-submit@freebsd.org
Subject: Re: kern/86306: [patch] if_em.c locks up while trying to send a highly fragmented packet
Date: Mon, 19 Sep 2005 09:29:26 +0300

 Hi Dmitrij,
 
 On Sun, Sep 18, 2005 at 11:25:35PM +0400, Dmitrij Tejblum wrote:
 > When em_encap() tries to send a very long mbuf chain (i.e. more than
 > EM_MAX_SCATTER == 64 mbufs), bus_dmamap_load_mbuf_sg() may fail with EFBIG. 
 > Then em_encap() fail, the packet is not sent and left in the output queue, 
 > and thus no futher transmission is possible.
 > 
 > Some other driver handle similar condition with m_defrag(9) function
 > (which is intended for this purpose).
 > 
 Can you please modify your patch as follows:
 
 1) Count how much fragments are in the packet in em_encap() first, and
    do m_defrag() if it exceeeds EM_MAX_SCATTER, like in if_dc.c.  If it
    is still EFBIG after that and bus_dmamap_load_mbuf_sg(), then free it
    as you do to prevent re-enqueue.
 
 2) Put BPF processing back to em_start_locked().
 
 3) Pull up to the HEAD version of the driver.
 
 
 Cheers,
 -- 
 Ruslan Ermilov
 ru@FreeBSD.org
 FreeBSD committer

From: Dmitrij Tejblum <tejblum@yandex-team.ru>
To: Ruslan Ermilov <ru@freebsd.org>
Cc: FreeBSD-gnats-submit@freebsd.org
Subject: Re: kern/86306: [patch] if_em.c locks up while trying to send a highly
 fragmented packet
Date: Mon, 19 Sep 2005 11:38:47 +0400

 This is a multi-part message in MIME format.
 --------------080903090009080801040205
 Content-Type: text/plain; charset=ISO-8859-1; format=flowed
 Content-Transfer-Encoding: 7bit
 
 Ruslan Ermilov wrote:
 
 >Hi Dmitrij,
 >
 >On Sun, Sep 18, 2005 at 11:25:35PM +0400, Dmitrij Tejblum wrote:
 >  
 >
 >>When em_encap() tries to send a very long mbuf chain (i.e. more than
 >>EM_MAX_SCATTER == 64 mbufs), bus_dmamap_load_mbuf_sg() may fail with EFBIG. 
 >>Then em_encap() fail, the packet is not sent and left in the output queue, 
 >>and thus no futher transmission is possible.
 >>
 >>Some other driver handle similar condition with m_defrag(9) function
 >>(which is intended for this purpose).
 >>
 >>    
 >>
 >Can you please modify your patch as follows:
 >
 >1) Count how much fragments are in the packet in em_encap() first, and
 >   do m_defrag() if it exceeeds EM_MAX_SCATTER, like in if_dc.c.  If it
 >   is still EFBIG after that and bus_dmamap_load_mbuf_sg(), then free it
 >   as you do to prevent re-enqueue.
 >  
 >
 So you think that if_dc.c is a better example than e.g. if_fxp.c and 
 if_xl.c? Why? I also suspect that your suggestion would be a pessimisation.
 
 >2) Put BPF processing back to em_start_locked().
 >  
 >
 As I wrote, I think that if e.g. we were unable to defragment a packet 
 it is better to drop it and try to send the next, rather than stop and 
 set OACTIVE (since the code that clear OACTIVE assume that it is about 
 TX descriptors). (You didn't suggest to change that).  I moved BPF 
 processing since it would not be a good idea to pass NULL to BPF.
 
 >3) Pull up to the HEAD version of the driver.
 >  
 >
 Well, please answer 1 and 2 first :-).
 
 >
 >Cheers,
 >  
 >
 
 
 --------------080903090009080801040205
 Content-Type: text/html; charset=ISO-8859-1
 Content-Transfer-Encoding: 7bit
 
 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <html>
 <head>
   <meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">
 </head>
 <body bgcolor="#ffffff" text="#000000">
 Ruslan Ermilov wrote:
 <blockquote cite="mid20050919062926.GF65954@ip.net.ua" type="cite">
   <pre wrap="">Hi Dmitrij,
 
 On Sun, Sep 18, 2005 at 11:25:35PM +0400, Dmitrij Tejblum wrote:
   </pre>
   <blockquote type="cite">
     <pre wrap="">When em_encap() tries to send a very long mbuf chain (i.e. more than
 EM_MAX_SCATTER == 64 mbufs), bus_dmamap_load_mbuf_sg() may fail with EFBIG. 
 Then em_encap() fail, the packet is not sent and left in the output queue, 
 and thus no futher transmission is possible.
 
 Some other driver handle similar condition with m_defrag(9) function
 (which is intended for this purpose).
 
     </pre>
   </blockquote>
   <pre wrap=""><!---->Can you please modify your patch as follows:
 
 1) Count how much fragments are in the packet in em_encap() first, and
    do m_defrag() if it exceeeds EM_MAX_SCATTER, like in if_dc.c.  If it
    is still EFBIG after that and bus_dmamap_load_mbuf_sg(), then free it
    as you do to prevent re-enqueue.
   </pre>
 </blockquote>
 So you think that if_dc.c is a better example than e.g. if_fxp.c and
 if_xl.c? Why? I also suspect that your suggestion would be a
 pessimisation.<br>
 <blockquote cite="mid20050919062926.GF65954@ip.net.ua" type="cite">
   <pre wrap="">
 2) Put BPF processing back to em_start_locked().
   </pre>
 </blockquote>
 As I wrote, I think that if e.g. we were unable to defragment a packet
 it is better to drop it and try to send the next, rather than stop and
 set OACTIVE (since the code that clear OACTIVE assume that it is about
 TX descriptors). (You didn't suggest to change that).&nbsp; I moved BPF
 processing since it would not be a good idea to pass NULL to BPF.<br>
 <blockquote cite="mid20050919062926.GF65954@ip.net.ua" type="cite">
   <pre wrap="">
 3) Pull up to the HEAD version of the driver.
   </pre>
 </blockquote>
 Well, please answer 1 and 2 first :-).<br>
 <blockquote cite="mid20050919062926.GF65954@ip.net.ua" type="cite">
   <pre wrap="">
 
 Cheers,
   </pre>
 </blockquote>
 <br>
 </body>
 </html>
 
 --------------080903090009080801040205--

From: Ruslan Ermilov <ru@freebsd.org>
To: Dmitrij Tejblum <tejblum@yandex-team.ru>
Cc: FreeBSD-gnats-submit@freebsd.org
Subject: Re: kern/86306: [patch] if_em.c locks up while trying to send a highly fragmented packet
Date: Mon, 19 Sep 2005 11:09:46 +0300

 On Mon, Sep 19, 2005 at 11:38:47AM +0400, Dmitrij Tejblum wrote:
 >    Ruslan Ermilov wrote:
 > 
 >  Hi Dmitrij,
 > 
 >  On Sun, Sep 18, 2005 at 11:25:35PM +0400, Dmitrij Tejblum wrote:
 > 
 > 
 >  When em_encap() tries to send a very long mbuf chain (i.e. more than
 >  EM_MAX_SCATTER == 64 mbufs), bus_dmamap_load_mbuf_sg() may fail with EFBIG.
 >  Then em_encap() fail, the packet is not sent and left in the output queue,
 >  and thus no futher transmission is possible.
 > 
 >  Some other driver handle similar condition with m_defrag(9) function
 >  (which is intended for this purpose).
 > 
 > 
 > 
 >  Can you please modify your patch as follows:
 > 
 >  1) Count how much fragments are in the packet in em_encap() first, and
 >     do m_defrag() if it exceeeds EM_MAX_SCATTER, like in if_dc.c.  If it
 >     is still EFBIG after that and bus_dmamap_load_mbuf_sg(), then free it
 >     as you do to prevent re-enqueue.
 > 
 > 
 >    So you think that if_dc.c is a better example than e.g. if_fxp.c and
 >    if_xl.c? Why? I also suspect that your suggestion would be a
 >    pessimisation.
 > 
 Checking for a chain length shouldn't be much of pessimization, it's
 very fast, and I thought it'd save code duplication.  But I don't
 insist on this one.  If you would like to stay with try-and-fail
 approach, I don't mind.
 
 >  2) Put BPF processing back to em_start_locked().
 > 
 > 
 >    As I wrote, I think that if e.g. we were unable to defragment a packet it
 >    is better to drop it and try to send the next, rather than stop and set
 >    OACTIVE (since the code that clear OACTIVE assume that it is about TX
 >    descriptors). (You didn't suggest to change that).  I moved BPF processing
 >    since it would not be a good idea to pass NULL to BPF.
 > 
 I don't understand how moving BPF processing in em_encap() helps this,
 and how we can pass a NULL pointer if BPF processing stayed where it was,
 in start().  Also, in your patch, if either DMA loading of mbuf fails or
 mbuf chain defragmentation fails, NULL will be returned and no next
 packet will be processed (though I agree that in the latter case it
 would be logical to try the next packet).
 
 
 Cheers,
 -- 
 Ruslan Ermilov
 ru@FreeBSD.org
 FreeBSD committer

From: Dmitrij Tejblum <tejblum@yandex-team.ru>
To: Ruslan Ermilov <ru@freebsd.org>
Cc: FreeBSD-gnats-submit@freebsd.org
Subject: Re: kern/86306: [patch] if_em.c locks up while trying to send a
 highly fragmented packet
Date: Mon, 3 Oct 2005 00:29:28 +0400 (MSD)

 Sorry for long delay.
 
 Ruslan Ermilov wrote:
 > On Mon, Sep 19, 2005 at 11:38:47AM +0400, Dmitrij Tejblum wrote:
 >
 >>   Ruslan Ermilov wrote:
 >>
 >> Hi Dmitrij,
 >>
 >> On Sun, Sep 18, 2005 at 11:25:35PM +0400, Dmitrij Tejblum wrote:
 >>
 >>
 >> When em_encap() tries to send a very long mbuf chain (i.e. more than
 >> EM_MAX_SCATTER == 64 mbufs), bus_dmamap_load_mbuf_sg() may fail with EFBIG.
 >> Then em_encap() fail, the packet is not sent and left in the output queue,
 >> and thus no futher transmission is possible.
 >>
 >> Some other driver handle similar condition with m_defrag(9) function
 >> (which is intended for this purpose).
 >>
 >>
 >>
 >> Can you please modify your patch as follows:
 >>
 >> 1) Count how much fragments are in the packet in em_encap() first, and
 >>    do m_defrag() if it exceeeds EM_MAX_SCATTER, like in if_dc.c.  If it
 >>    is still EFBIG after that and bus_dmamap_load_mbuf_sg(), then free it
 >>    as you do to prevent re-enqueue.
 >>
 >>
 >>   So you think that if_dc.c is a better example than e.g. if_fxp.c and
 >>   if_xl.c? Why? I also suspect that your suggestion would be a
 >>   pessimisation.
 >>
 >
 > Checking for a chain length shouldn't be much of pessimization, it's
 > very fast, and I thought it'd save code duplication.  But I don't
 > insist on this one.  If you would like to stay with try-and-fail
 > approach, I don't mind.
 >
 >
 >> 2) Put BPF processing back to em_start_locked().
 >>
 >>
 >>   As I wrote, I think that if e.g. we were unable to defragment a packet it
 >>   is better to drop it and try to send the next, rather than stop and set
 >>   OACTIVE (since the code that clear OACTIVE assume that it is about TX
 >>   descriptors). (You didn't suggest to change that).  I moved BPF processing
 >>   since it would not be a good idea to pass NULL to BPF.
 >>
 >
 > I don't understand how moving BPF processing in em_encap() helps this,
 > and how we can pass a NULL pointer if BPF processing stayed where it was,
 > in start().  Also, in your patch, if either DMA loading of mbuf fails or
 > mbuf chain defragmentation fails, NULL will be returned and no next
 > packet will be processed (though I agree that in the latter case it
 > would be logical to try the next packet).
 
 em_encap() returns an error code (though the value is only checked for
 zero and otherwise unused). If em_encap() returns a (non-zero) error,
 em_start_locked() breaks out of the loop, and if em_encap() returns
 "success" (zero), it continues the loop and, with the code in CVS,
 send the mbuf to BPF. When I drop packet I want to continue the loop
 and return 0, so I have to deal with BPF handling somehow.
 
 Below is updated patch. It is generated against -current, but also
 applicable to RELENG_5, since the driver is the same in the places I
 touch. (Frankly I only tried to run it with RELENG_5 kernel.)
 Code duplication is decreased. I also moved DMA setup before VLAN
 processing, since I noticed that the VLAN processing might change the mbuf
 chain. Also I changed the VLAN processing to return 0 in case of mbuf
 failures for abovementioned reasons.
 
 Index: sys/dev/em/if_em.c
 ===================================================================
 RCS file: /home/ncvs/src/sys/dev/em/if_em.c,v
 retrieving revision 1.73
 diff -u -p -r1.73 if_em.c
 --- sys/dev/em/if_em.c	29 Sep 2005 13:23:34 -0000	1.73
 +++ sys/dev/em/if_em.c	2 Oct 2005 20:03:21 -0000
 @@ -623,13 +623,6 @@ em_start_locked(struct ifnet *ifp)
  			break;
                  }
 
 -		/* Send a copy of the frame to the BPF listener */
 -#if __FreeBSD_version < 500000
 -                if (ifp->if_bpf)
 -                        bpf_mtap(ifp, m_head);
 -#else
 -		BPF_MTAP(ifp, m_head);
 -#endif
 
                  /* Set timeout in case hardware has problems transmitting */
                  ifp->if_timer = EM_TX_TIMEOUT;
 @@ -1209,36 +1202,6 @@ em_encap(struct adapter *adapter, struct
                  }
          }
 
 -        /*
 -         * Map the packet for DMA.
 -         */
 -        if (bus_dmamap_create(adapter->txtag, BUS_DMA_NOWAIT, &map)) {
 -                adapter->no_tx_map_avail++;
 -                return (ENOMEM);
 -        }
 -        error = bus_dmamap_load_mbuf_sg(adapter->txtag, map, m_head, segs,
 -					&nsegs, BUS_DMA_NOWAIT);
 -        if (error != 0) {
 -                adapter->no_tx_dma_setup++;
 -                bus_dmamap_destroy(adapter->txtag, map);
 -                return (error);
 -        }
 -        KASSERT(nsegs != 0, ("em_encap: empty packet"));
 -
 -        if (nsegs > adapter->num_tx_desc_avail) {
 -                adapter->no_tx_desc_avail2++;
 -                bus_dmamap_destroy(adapter->txtag, map);
 -                return (ENOBUFS);
 -        }
 -
 -
 -        if (ifp->if_hwassist > 0) {
 -                em_transmit_checksum_setup(adapter,  m_head,
 -                                           &txd_upper, &txd_lower);
 -        } else
 -                txd_upper = txd_lower = 0;
 -
 -
          /* Find out if we are in vlan mode */
  #if __FreeBSD_version < 500000
          if ((m_head->m_flags & (M_PROTO1|M_PKTHDR)) == (M_PROTO1|M_PKTHDR) &&
 @@ -1261,22 +1224,19 @@ em_encap(struct adapter *adapter, struct
 
  		m_head = m_pullup(m_head, sizeof(eh));
  		if (m_head == NULL) {
 -			*m_headp = NULL;
 -                	bus_dmamap_destroy(adapter->txtag, map);
 -			return (ENOBUFS);
 +			adapter->mbuf_alloc_failed++;
 +			goto drop2;
  		}
  		eh = *mtod(m_head, struct ether_header *);
  		M_PREPEND(m_head, sizeof(*evl), M_DONTWAIT);
  		if (m_head == NULL) {
 -			*m_headp = NULL;
 -                	bus_dmamap_destroy(adapter->txtag, map);
 -			return (ENOBUFS);
 +			adapter->mbuf_alloc_failed++;
 +			goto drop2;
  		}
  		m_head = m_pullup(m_head, sizeof(*evl));
  		if (m_head == NULL) {
 -			*m_headp = NULL;
 -                	bus_dmamap_destroy(adapter->txtag, map);
 -			return (ENOBUFS);
 +			adapter->mbuf_alloc_failed++;
 +			goto drop2;
  		}
  		evl = mtod(m_head, struct ether_vlan_header *);
  		bcopy(&eh, evl, sizeof(*evl));
 @@ -1288,6 +1248,54 @@ em_encap(struct adapter *adapter, struct
  		*m_headp = m_head;
  	}
 
 +        /*
 +         * Map the packet for DMA.
 +         */
 +        if (bus_dmamap_create(adapter->txtag, BUS_DMA_NOWAIT, &map)) {
 +                adapter->no_tx_map_avail++;
 +                return (ENOMEM);
 +        }
 +        error = bus_dmamap_load_mbuf_sg(adapter->txtag, map, m_head, segs,
 +					&nsegs, BUS_DMA_NOWAIT);
 +        if (error != 0 && error != EFBIG) {
 +                printf("em%d: can't map mbuf (error %d)\n",
 +                        adapter->unit, error);
 +                adapter->no_tx_dma_setup++;
 +                goto drop;
 +        } else if (error == EFBIG) {
 +                struct mbuf *mn;
 +                mn = m_defrag(m_head, M_DONTWAIT);
 +                if (mn == NULL) {
 +                        printf("em%d: can't defrag mbuf\n", adapter->unit);
 +                        adapter->mbuf_alloc_failed++;
 +                        goto drop;
 +                }
 +                m_head = mn;
 +                error = bus_dmamap_load_mbuf_sg(adapter->txtag, map, m_head,
 +                                                segs, &nsegs, BUS_DMA_NOWAIT);
 +                if (error != 0) {
 +                        printf("em%d: can't map mbuf2 (error %d)\n",
 +                                adapter->unit, error);
 +                        adapter->no_tx_dma_setup++;
 +                        goto drop;
 +                }
 +        }
 +        KASSERT(nsegs != 0, ("em_encap: empty packet"));
 +
 +        if (nsegs > adapter->num_tx_desc_avail) {
 +                adapter->no_tx_desc_avail2++;
 +                bus_dmamap_destroy(adapter->txtag, map);
 +                return (ENOBUFS);
 +        }
 +
 +
 +        if (ifp->if_hwassist > 0) {
 +                em_transmit_checksum_setup(adapter,  m_head,
 +                                           &txd_upper, &txd_lower);
 +        } else
 +                txd_upper = txd_lower = 0;
 +
 +
          i = adapter->next_avail_tx_desc;
  	if (adapter->pcix_82544) {
  		txd_saved = i;
 @@ -1389,7 +1397,21 @@ em_encap(struct adapter *adapter, struct
                  }
          }
 
 +        /* Send a copy of the frame to the BPF listener */
 +#if __FreeBSD_version < 500000
 +        if (ifp->if_bpf)
 +               bpf_mtap(ifp, m_head);
 +#else
 +        BPF_MTAP(ifp, m_head);
 +#endif
          return(0);
 +drop:
 +        m_freem(m_head);
 +drop2:
 +        *m_headp = NULL;
 +        bus_dmamap_destroy(adapter->txtag, map);
 +        return (0);
 +
  }
 
  /*********************************************************************
 @@ -3264,7 +3286,8 @@ em_update_stats_counters(struct adapter
  	adapter->stats.mpc + adapter->stats.cexterr;
 
  	/* Tx Errors */
 -	ifp->if_oerrors = adapter->stats.ecol + adapter->stats.latecol;
 +	ifp->if_oerrors = adapter->stats.ecol + adapter->stats.latecol +
 +		adapter->no_tx_dma_setup + adapter->no_tx_map_avail;
 
  }
 
 
 >
 >
 > Cheers,
 
 

From: Vladimir Ivanov <wawa@yandex-team.ru>
To: bug-followup@FreeBSD.org, tejblum@yandex-team.ru
Cc:  
Subject: Re: kern/86306: [em] [patch] if_em.c locks up while trying to send
 a highly fragmented packet
Date: Tue, 01 Aug 2006 13:56:44 +0400

 This is a cryptographically signed message in MIME format.
 
 --------------ms000200080501050608020709
 Content-Type: text/plain; charset=KOI8-R; format=flowed
 Content-Transfer-Encoding: 7bit
 
 Hello all,
 
 Actually, this bug have to be considered as blocker (for jumbo packets 
 mode at least). That's why it should be applied ASAP. I can't  believe 
 it still didn't
 :-(
 
 WBR,
 
 -- 
 Vladimir Ivanov
 Network Operations Center
 OOO "Yandex"
 t: +7 495 739-7000
 f: +7 495 739-7070
 @: noc@yandex.net (corporate)
   wawa@yandex-team.ru (personal)
   www: www.yandex.ru
 -- 
 
 
 --------------ms000200080501050608020709
 Content-Type: application/x-pkcs7-signature; name="smime.p7s"
 Content-Transfer-Encoding: base64
 Content-Disposition: attachment; filename="smime.p7s"
 Content-Description: S/MIME Cryptographic Signature
 
 MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIIGJzCC
 AuAwggJJoAMCAQICEFuWN3fzFL7yRhcuYyvn3cgwDQYJKoZIhvcNAQEEBQAwYjELMAkGA1UE
 BhMCWkExJTAjBgNVBAoTHFRoYXd0ZSBDb25zdWx0aW5nIChQdHkpIEx0ZC4xLDAqBgNVBAMT
 I1RoYXd0ZSBQZXJzb25hbCBGcmVlbWFpbCBJc3N1aW5nIENBMB4XDTA2MDYyODE1MjAxMVoX
 DTA3MDYyODE1MjAxMVowRTEfMB0GA1UEAxMWVGhhd3RlIEZyZWVtYWlsIE1lbWJlcjEiMCAG
 CSqGSIb3DQEJARYTd2F3YUB5YW5kZXgtdGVhbS5ydTCCASIwDQYJKoZIhvcNAQEBBQADggEP
 ADCCAQoCggEBAM1EpYvBCs5XMLDPDg5tRbD+cPCbBxVjVosITiajgg7eRtgIewxyNoIPC8TY
 KkUfbJTO33s09XmfbYjQhtWQA4mFRIgSJqy5WtXdSl1+Gjq2MMy7TZjN0CH6boshmGnxjW/D
 0FV8qm4PebXD1PDWokmOx+etcudCr2WSPZ0oPdqS2EkWgClLK6v7qjdm8oTF5rA+ro1t1KXh
 RvnYxYv0nz0moWG0G8RPtQ2kNpODbmbEBqKl2pTrOw+o6nY7Z47FJXEZiqpPBLXUV+2ykYey
 2PT3lZtYwHOh76kh3HdsVVd8UQVfalCZNNJJkZXD0QRfxByBEGHLdYC34SRzvyHK/HkCAwEA
 AaMwMC4wHgYDVR0RBBcwFYETd2F3YUB5YW5kZXgtdGVhbS5ydTAMBgNVHRMBAf8EAjAAMA0G
 CSqGSIb3DQEBBAUAA4GBAIj8aIRL9pal/v0odxMweiFvOdTJBI3Ov/mmA0FNrxeSDD9ALUy5
 ROAqyuvIxjkyisxlx1iAtMGmPuu+9vVGT8W4ZcO8PdCFjXnvUV1ec+lNKKlGO4Hbh9Q9MKi7
 Gg1wKN5G1OdDGlHkHnGNIS9R3WPSSFdm7+GAnCOTNsL6gzGsMIIDPzCCAqigAwIBAgIBDTAN
 BgkqhkiG9w0BAQUFADCB0TELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTES
 MBAGA1UEBxMJQ2FwZSBUb3duMRowGAYDVQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UE
 CxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEkMCIGA1UEAxMbVGhhd3RlIFBl
 cnNvbmFsIEZyZWVtYWlsIENBMSswKQYJKoZIhvcNAQkBFhxwZXJzb25hbC1mcmVlbWFpbEB0
 aGF3dGUuY29tMB4XDTAzMDcxNzAwMDAwMFoXDTEzMDcxNjIzNTk1OVowYjELMAkGA1UEBhMC
 WkExJTAjBgNVBAoTHFRoYXd0ZSBDb25zdWx0aW5nIChQdHkpIEx0ZC4xLDAqBgNVBAMTI1Ro
 YXd0ZSBQZXJzb25hbCBGcmVlbWFpbCBJc3N1aW5nIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GN
 ADCBiQKBgQDEpjxVc1X7TrnKmVoeaMB1BHCd3+n/ox7svc31W/Iadr1/DDph8r9RzgHU5VAK
 MNcCY1osiRVwjt3J8CuFWqo/cVbLrzwLB+fxH5E2JCoTzyvV84J3PQO+K/67GD4Hv0CAAmTX
 p6a7n2XRxSpUhQ9IBH+nttE8YQRAHmQZcmC3+wIDAQABo4GUMIGRMBIGA1UdEwEB/wQIMAYB
 Af8CAQAwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2NybC50aGF3dGUuY29tL1RoYXd0ZVBl
 cnNvbmFsRnJlZW1haWxDQS5jcmwwCwYDVR0PBAQDAgEGMCkGA1UdEQQiMCCkHjAcMRowGAYD
 VQQDExFQcml2YXRlTGFiZWwyLTEzODANBgkqhkiG9w0BAQUFAAOBgQBIjNFQg+oLLswNo2as
 Zw9/r6y+whehQ5aUnX9MIbj4Nh+qLZ82L8D0HFAgk3A8/a3hYWLD2ToZfoSxmRsAxRoLgnSe
 JVCUYsfbJ3FXJY3dqZw5jowgT2Vfldr394fWxghOrvbqNOUQGls1TXfjViF4gtwhGTXeJLHT
 HUb/XV9lTzGCAlEwggJNAgEBMHYwYjELMAkGA1UEBhMCWkExJTAjBgNVBAoTHFRoYXd0ZSBD
 b25zdWx0aW5nIChQdHkpIEx0ZC4xLDAqBgNVBAMTI1RoYXd0ZSBQZXJzb25hbCBGcmVlbWFp
 bCBJc3N1aW5nIENBAhBbljd38xS+8kYXLmMr593IMAkGBSsOAwIaBQCggbEwGAYJKoZIhvcN
 AQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMDYwODAxMDk1NjQ0WjAjBgkqhkiG
 9w0BCQQxFgQUSOM035UOz2leisoIWoSplK9ax0AwUgYJKoZIhvcNAQkPMUUwQzAKBggqhkiG
 9w0DBzAOBggqhkiG9w0DAgICAIAwDQYIKoZIhvcNAwICAUAwBwYFKw4DAgcwDQYIKoZIhvcN
 AwICASgwDQYJKoZIhvcNAQEBBQAEggEAshP4FYqJAhzufrApz2SkmFAIxPQNBpYL//7Ad370
 hpKoXK3N4T8L0jCtio6+kGB0vsM0dS/n1x3NZSiAfNVqpamZ1kbm55C2Xgky02SAFenvB3/3
 LyBCK8tWc+lc7AYglwjzFvqiujA1aHhV2lBj8dapoSZGjYZttILUvcoOeSop0wBB3rXfx1KD
 iLrd/Tg92BmJULskt22bMaj+wOwA2hIZMe1BZWsjWyVPYwKre7wZM1vyAyvnOQLQy3Kqbbb9
 GeBLRsdUAdrvgEsoXYZ+hgpiSLkl5G8VTJXfxQbgi1GpiZVaKZP66+t73WEtORlBgh0f+AJ4
 DhM8ouw3WZ7iXQAAAAAAAA==
 --------------ms000200080501050608020709--
Responsible-Changed-From-To: freebsd-bugs->yongari 
Responsible-Changed-By: glebius 
Responsible-Changed-When: Mon Aug 14 09:18:33 UTC 2006 
Responsible-Changed-Why:  


http://www.freebsd.org/cgi/query-pr.cgi?pr=86306 
State-Changed-From-To: open->patched 
State-Changed-By: glebius 
State-Changed-When: Mon Aug 14 09:19:06 UTC 2006 
State-Changed-Why:  
Looks like Pyun has committed fix to HEAD. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=86306 
State-Changed-From-To: patched->closed 
State-Changed-By: remko 
State-Changed-When: Mon Mar 26 20:38:41 UTC 2007 
State-Changed-Why:  
assume this got fixed already. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=86306 
>Unformatted:
