Module Name:    src
Committed By:   jdolecek
Date:           Fri Jul 17 10:56:15 UTC 2020

Modified Files:
        src/sys/dev/pci: if_bnx.c

Log Message:
if bnx_tx_encap() fails because mbuf is too fragmented or too long,
drop the mbuf instead of wedging the TX queue forever; found by code inspection

this is quite unlikely scenario since it requires mbuf chain consisting of
more than 8 frags and m_defrag() failing, so probably unrelated to PR kern/47229


To generate a diff of this commit:
cvs rdiff -u -r1.104 -r1.105 src/sys/dev/pci/if_bnx.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/pci/if_bnx.c
diff -u src/sys/dev/pci/if_bnx.c:1.104 src/sys/dev/pci/if_bnx.c:1.105
--- src/sys/dev/pci/if_bnx.c:1.104	Fri Jul 17 10:08:04 2020
+++ src/sys/dev/pci/if_bnx.c	Fri Jul 17 10:56:15 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_bnx.c,v 1.104 2020/07/17 10:08:04 jdolecek Exp $	*/
+/*	$NetBSD: if_bnx.c,v 1.105 2020/07/17 10:56:15 jdolecek Exp $	*/
 /*	$OpenBSD: if_bnx.c,v 1.101 2013/03/28 17:21:44 brad Exp $	*/
 
 /*-
@@ -35,7 +35,7 @@
 #if 0
 __FBSDID("$FreeBSD: src/sys/dev/bce/if_bce.c,v 1.3 2006/04/13 14:12:26 ru Exp $");
 #endif
-__KERNEL_RCSID(0, "$NetBSD: if_bnx.c,v 1.104 2020/07/17 10:08:04 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_bnx.c,v 1.105 2020/07/17 10:56:15 jdolecek Exp $");
 
 /*
  * The following controllers are supported by this driver:
@@ -5174,8 +5174,10 @@ retry:
 	bus_dmamap_sync(sc->bnx_dmatag, map, 0, map->dm_mapsize,
 	    BUS_DMASYNC_PREWRITE);
 	/* Make sure there's room in the chain */
-	if (map->dm_nsegs > (sc->max_tx_bd - sc->used_tx_bd))
+	if (map->dm_nsegs > (sc->max_tx_bd - sc->used_tx_bd)) {
+		error = ENOMEM;
 		goto nospace;
+	}
 
 	/* prod points to an empty tx_bd at this point. */
 	prod_bseq = sc->tx_prod_bseq;
@@ -5254,7 +5256,7 @@ maperr:
 	TAILQ_INSERT_TAIL(&sc->tx_free_pkts, pkt, pkt_entry);
 	mutex_exit(&sc->tx_pkt_mtx);
 
-	return ENOMEM;
+	return error;
 }
 
 /****************************************************************************/
@@ -5268,7 +5270,7 @@ bnx_start(struct ifnet *ifp)
 {
 	struct bnx_softc	*sc = ifp->if_softc;
 	struct mbuf		*m_head = NULL;
-	int			count = 0;
+	int			count = 0, error;
 #ifdef BNX_DEBUG
 	uint16_t		tx_chain_prod;
 #endif
@@ -5306,12 +5308,22 @@ bnx_start(struct ifnet *ifp)
 		 * don't have room, set the OACTIVE flag to wait
 		 * for the NIC to drain the chain.
 		 */
-		if (bnx_tx_encap(sc, m_head)) {
-			ifp->if_flags |= IFF_OACTIVE;
-			DBPRINT(sc, BNX_INFO_SEND, "TX chain is closed for "
-			    "business! Total tx_bd used = %d\n",
-			    sc->used_tx_bd);
-			break;
+		if ((error = bnx_tx_encap(sc, m_head))) {
+			if (error == ENOMEM) {
+				ifp->if_flags |= IFF_OACTIVE;
+				DBPRINT(sc, BNX_INFO_SEND,
+				    "TX chain is closed for "
+				    "business! Total tx_bd used = %d\n",
+				    sc->used_tx_bd);
+				break;
+			} else {
+				/* Permanent error for the mbuf, drop it */
+				IFQ_DEQUEUE(&ifp->if_snd, m_head);
+				m_freem(m_head);
+				DBPRINT(sc, BNX_INFO_SEND,
+				    "mbuf load error %d, dropped\n", error);
+				continue;
+			}
 		}
 
 		IFQ_DEQUEUE(&ifp->if_snd, m_head);

Reply via email to