From owner-freebsd-bugs@FreeBSD.ORG Sun Sep 18 19:30:06 2005 Return-Path: X-Original-To: freebsd-bugs@hub.freebsd.org Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 2EC4D16A41F for ; Sun, 18 Sep 2005 19:30:06 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id EC43A43D49 for ; Sun, 18 Sep 2005 19:30:04 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.13.3/8.13.3) with ESMTP id j8IJU4J6098651 for ; Sun, 18 Sep 2005 19:30:04 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.13.3/8.13.1/Submit) id j8IJU4bI098618; Sun, 18 Sep 2005 19:30:04 GMT (envelope-from gnats) Resent-Date: Sun, 18 Sep 2005 19:30:04 GMT Resent-Message-Id: <200509181930.j8IJU4bI098618@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Dmitrij Tejblum Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 9AC7216A41F for ; 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 ; 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 ; 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 To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Cc: Subject: kern/86306: [patch] if_em.c locks up while trying to send a highly fragmented packet X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Dmitrij Tejblum List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 18 Sep 2005 19:30:06 -0000 >Number: 86306 >Category: kern >Synopsis: [patch] if_em.c locks up while trying to send a highly fragmented packet >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Sun Sep 18 19:30:04 GMT 2005 >Closed-Date: >Last-Modified: >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: >Unformatted: