Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 31 Mar 2011 21:30:00 +0000 (UTC)
From:      David Christensen <davidch@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r220226 - head/sys/dev/bxe
Message-ID:  <201103312130.p2VLU0fG023271@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: davidch
Date: Thu Mar 31 21:30:00 2011
New Revision: 220226
URL: http://svn.freebsd.org/changeset/base/220226

Log:
  - Added debug support to monitor mbuf defrag attempts/failures.
  
  MFC after:	One week.

Modified:
  head/sys/dev/bxe/if_bxe.c
  head/sys/dev/bxe/if_bxe.h

Modified: head/sys/dev/bxe/if_bxe.c
==============================================================================
--- head/sys/dev/bxe/if_bxe.c	Thu Mar 31 21:21:07 2011	(r220225)
+++ head/sys/dev/bxe/if_bxe.c	Thu Mar 31 21:30:00 2011	(r220226)
@@ -352,7 +352,7 @@ static int bxe_sysctl_reg_read(SYSCTL_HA
 static int bxe_sysctl_breakpoint(SYSCTL_HANDLER_ARGS);
 static void bxe_validate_rx_packet(struct bxe_fastpath *, uint16_t,
 	    union eth_rx_cqe *, struct mbuf *);
-static void bxe_dump_grc(struct bxe_softc *, int);
+static void bxe_grcdump(struct bxe_softc *, int);
 static void bxe_dump_enet(struct bxe_softc *,struct mbuf *);
 static void bxe_dump_mbuf (struct bxe_softc *, struct mbuf *);
 static void bxe_dump_tx_mbuf_chain(struct bxe_softc *, int, int);
@@ -8585,16 +8585,22 @@ bxe_tx_encap(struct bxe_fastpath *fp, st
 	error = bus_dmamap_load_mbuf_sg(fp->tx_mbuf_tag, map, m0,
 	    segs, &nsegs, BUS_DMA_NOWAIT);
 	do{
-	/* Handle any mapping errors. */
+		/* Handle any mapping errors. */
 		if(__predict_false(error)){
 			if (error == ENOMEM) {
+				/* Temporary OS resource issue. */
 				rc = ENOMEM;
 			}else if (error == EFBIG) {
+				/* Possibly recoverable. */
+				DBRUN(fp->mbuf_defrag_attempts++);
 				m0 = m_defrag(*m_head, M_DONTWAIT);
 				if (m0 == NULL) {
+					BXE_PRINTF("%s(%d): Can't defrag TX frame!\n",
+					    __FILE__, __LINE__);
 					rc = ENOBUFS;
 				} else {
 				/* Defrag was successful, try mapping again.*/
+					DBRUN(fp->mbuf_defrag_successes++);
 					*m_head = m0;
 					error =
 					    bus_dmamap_load_mbuf_sg(
@@ -8602,10 +8608,15 @@ bxe_tx_encap(struct bxe_fastpath *fp, st
 						segs, &nsegs, BUS_DMA_NOWAIT);
 				}
 			}else {
+				/* Unrecoverable. */
+				BXE_PRINTF("%s(%d): Unknown TX mapping error! "
+				    "rc = %d.\n", __FILE__, __LINE__, error);
+				DBRUN(bxe_dump_mbuf(sc, m0));
 				rc = error;
 			}
 			break;
 		}
+
 		/*
 		 * Now that we know how many buffer descriptors	are required to
 		 * send the frame, check whether we have enough transmit BD's
@@ -8615,29 +8626,39 @@ bxe_tx_encap(struct bxe_fastpath *fp, st
 		if (__predict_false((nsegs + 2) >
 		    (USABLE_TX_BD - fp->used_tx_bd))) {
 			bus_dmamap_unload(fp->tx_mbuf_tag, map);
+			BXE_PRINTF("%s(%d): Insufficient TX queue space!\n",
+				   __FILE__, __LINE__);
+			/* DRC - Should we drop a frame with this error? */
 			rc = ENOBUFS;
 			break;
 		}
+
 		/* Now make sure it fits in the pkt window */
-		if (nsegs > 12) {
-		/* The mbuf has more segments than the controller can handle.
-		 * Try to defrag the mbuf if there are too many
-		 * segments.  If it can't be defragged then
-		 * drop the frame, log an error, and exit.
-		 * An alternative would be to use a bounce buffer.
-		 */
+		if (__predict_false(nsegs > 12)) {
+			/* The mbuf has more segments than the controller can
+			 * handle. Try to defrag the mbuf if there are too many
+			 * segments.  If it can't be defragged then
+			 * drop the frame, log an error, and exit.
+			 * An alternative would be to use a bounce buffer.
+			 */
 			if(m0->m_pkthdr.csum_flags & CSUM_TSO){
 				if (! bxe_chktso_window(sc,nsegs,segs,m0))
 					/* Send it */
 					break;
 			}
+
 			/* Defrag for non tso and if tso needs it */
+			DBRUN(fp->mbuf_defrag_attempts++);
 			m0 = m_defrag(*m_head, M_DONTWAIT);
 			if (m0 == NULL) {
+				BXE_PRINTF("%s(%d): Can't defrag TX frame!\n",
+				    __FILE__, __LINE__);
 				rc = ENOBUFS;
 				break;
 			}
+
 			/* Defrag was successful, try mapping again. */
+			DBRUN(fp->mbuf_defrag_successes++);
 			*m_head = m0;
 			error =
 			    bus_dmamap_load_mbuf_sg(
@@ -8654,6 +8675,8 @@ bxe_tx_encap(struct bxe_fastpath *fp, st
 					/* The frame can't be defragged,
 					 *  drop it.
 					 */
+					BXE_PRINTF("%s(%d): Can't map TX frame!\n",
+					    __FILE__, __LINE__);
 					rc = error;
 				}
 				break;
@@ -8663,6 +8686,8 @@ bxe_tx_encap(struct bxe_fastpath *fp, st
 				if (bxe_chktso_window(sc,nsegs,segs,m0))
 					rc = ENOBUFS;
 			} else if (nsegs > 12 ){
+				BXE_PRINTF("%s(%d): Too many fragments for a TSO "
+				    "frame!\n",	__FILE__, __LINE__);
 				rc = ENOBUFS;
 			}
 		}
@@ -8672,15 +8697,13 @@ bxe_tx_encap(struct bxe_fastpath *fp, st
 	if (rc){
 		if(rc == ENOMEM){
 			/* Recoverable try again later  */
-			BXE_PRINTF("%s(%d): Error mapping mbuf into TX chain"
-			   "returning pkt to queue\n",__FILE__, __LINE__);
+			BXE_PRINTF("%s(%d): Error mapping mbuf into TX chain, "
+			   "returning pkt to queue!\n",__FILE__, __LINE__);
 		}else{
 			fp->soft_tx_errors++;
 			DBRUN(fp->tx_mbuf_alloc--);
 			m_freem(*m_head);
 			*m_head = NULL;
-			BXE_PRINTF("%s(%d): Error mapping mbuf into TX chain"
-			    "Frame dropped \n",__FILE__, __LINE__);
 		}
 		return (rc);
 	}
@@ -14838,7 +14861,7 @@ bxe_rxeof(struct bxe_fastpath *fp)
 
 			/*
 			 * The high level logic used here is to
-			 * immediatley replace each	receive buffer
+			 * immediatley replace each receive buffer
 			 * as it is used so that the receive chain
 			 * is full at all times.  First we try to
 			 * allocate a new receive buffer, but if
@@ -15497,7 +15520,7 @@ bxe_sysctl_reg_read(SYSCTL_HANDLER_ARGS)
 *   0 for success, positive value for failure.
 */
 static int
-bxe_sysctl_dump_grc(SYSCTL_HANDLER_ARGS)
+bxe_sysctl_grcdump(SYSCTL_HANDLER_ARGS)
 {
 	struct bxe_softc *sc;
 	int error, result;
@@ -15510,10 +15533,10 @@ bxe_sysctl_dump_grc(SYSCTL_HANDLER_ARGS)
 
 	if (result == 1) {
 		/* Generate a grcdump and log the contents.*/
-		bxe_dump_grc(sc, 1);
+		bxe_grcdump(sc, 1);
 	} else {
 		/* Generate a grcdump and don't log the contents. */
-		bxe_dump_grc(sc, 0);
+		bxe_grcdump(sc, 0);
 	}
 
 	return (error);
@@ -15555,13 +15578,18 @@ bxe_sysctl_breakpoint(SYSCTL_HANDLER_ARG
 static void
 bxe_add_sysctls(struct bxe_softc *sc)
 {
-	struct sysctl_ctx_list *ctx;
-	struct sysctl_oid_list *children;
-	struct bxe_eth_stats *estats;
+	struct sysctl_ctx_list *ctx =
+	    device_get_sysctl_ctx(sc->bxe_dev);
+	struct sysctl_oid_list *children =
+	    SYSCTL_CHILDREN(device_get_sysctl_tree(sc->bxe_dev));
+	struct bxe_eth_stats *estats = &sc->eth_stats;
+
+	struct sysctl_oid *queue_node;
+	    struct sysctl_oid_list *queue_list;
+
+#define QUEUE_NAME_LEN 32
+	char namebuf[QUEUE_NAME_LEN];
 
-	estats = &sc->eth_stats;
-	ctx = device_get_sysctl_ctx(sc->bxe_dev);
-	children = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->bxe_dev));
 
 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
 	    "estats_total_bytes_received_hi",
@@ -15676,36 +15704,60 @@ bxe_add_sysctls(struct bxe_softc *sc)
 	    CTLFLAG_RD, &sc->mbuf_alloc_failed, 0,
 	    "mbuf cluster allocation failures");
 
+	for (int i = 0; i < sc->num_queues; i++) {
+		struct bxe_fastpath *fp	= &sc->fp[i];
+		snprintf(namebuf, QUEUE_NAME_LEN, "fp[%02d]", i);
+
+		queue_node = SYSCTL_ADD_NODE(ctx, children, OID_AUTO,
+		    namebuf, CTLFLAG_RD, NULL, "Queue Name");
+		queue_list = SYSCTL_CHILDREN(queue_node);
+
+		SYSCTL_ADD_ULONG(ctx, queue_list, OID_AUTO,
+		    "mbuf_alloc_failed",
+		    CTLFLAG_RD, &fp->mbuf_alloc_failed,
+		    "Mbuf allocation failures");
+
+		SYSCTL_ADD_ULONG(ctx, queue_list, OID_AUTO,
+		    "mbuf_defrag_attempts",
+		    CTLFLAG_RD, &fp->mbuf_defrag_attempts,
+		    "Mbuf defrag attempts");
+
+		SYSCTL_ADD_ULONG(ctx, queue_list, OID_AUTO,
+		    "mbuf_defrag_successes",
+		    CTLFLAG_RD, &fp->mbuf_defrag_successes,
+		    "Mbuf defrag successes");
+	}
+
 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "driver_state",
-	    CTLTYPE_INT | CTLFLAG_RW, (void *)sc, 0, bxe_sysctl_driver_state,
-	    "I", "Drive state information");
+	    CTLTYPE_INT | CTLFLAG_RW, (void *)sc, 0,
+	    bxe_sysctl_driver_state, "I", "Drive state information");
 
 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "hw_state",
-	    CTLTYPE_INT | CTLFLAG_RW, (void *)sc, 0, bxe_sysctl_hw_state,
-	    "I", "Hardware state information");
+	    CTLTYPE_INT | CTLFLAG_RW, (void *)sc, 0,
+	    bxe_sysctl_hw_state, "I", "Hardware state information");
 
 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "dump_fw",
-	    CTLTYPE_INT | CTLFLAG_RW, (void *)sc, 0, bxe_sysctl_dump_fw,
-	    "I", "Dump MCP firmware");
+	    CTLTYPE_INT | CTLFLAG_RW, (void *)sc, 0,
+	    bxe_sysctl_dump_fw,	"I", "Dump MCP firmware");
 
 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "dump_rx_chain",
-	    CTLTYPE_INT | CTLFLAG_RW, (void *)sc, 0, bxe_sysctl_dump_rx_chain,
-	    "I", "Dump rx_bd chain");
+	    CTLTYPE_INT | CTLFLAG_RW, (void *)sc, 0,
+	    bxe_sysctl_dump_rx_chain, "I", "Dump rx_bd chain");
 
 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "dump_cqe_chain",
-	    CTLTYPE_INT | CTLFLAG_RW, (void *)sc, 0, bxe_sysctl_dump_cqe_chain,
-	    "I", "Dump cqe chain");
+	    CTLTYPE_INT | CTLFLAG_RW, (void *)sc, 0,
+	    bxe_sysctl_dump_cqe_chain, "I", "Dump cqe chain");
 
 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "dump_tx_chain",
-	    CTLTYPE_INT | CTLFLAG_RW, (void *)sc, 0, bxe_sysctl_dump_tx_chain,
-	    "I", "Dump tx_bd chain");
+	    CTLTYPE_INT | CTLFLAG_RW, (void *)sc, 0,
+	    bxe_sysctl_dump_tx_chain, "I", "Dump tx_bd chain");
 
 	/*
 	 * Generates a GRCdump (run sysctl dev.bxe.0.grcdump=0
-	 * before access buffer below).
+	 * before accessing buffer below).
 	 */
 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "grcdump",
-	    CTLTYPE_INT | CTLFLAG_RW, (void *)sc, 0, bxe_sysctl_dump_grc,
+	    CTLTYPE_INT | CTLFLAG_RW, (void *)sc, 0, bxe_sysctl_grcdump,
 	    "I", "Initiate a grcdump operation");
 
 	/*
@@ -15713,16 +15765,17 @@ bxe_add_sysctls(struct bxe_softc *sc)
 	 *  Use "sysctl -b dev.bxe.0.grcdump_buffer > buf.bin".
 	 */
 	SYSCTL_ADD_OPAQUE(ctx, children, OID_AUTO, "grcdump_buffer",
-	    CTLFLAG_RD | CTLFLAG_SKIP, sc->grcdump_buffer, BXE_GRCDUMP_BUF_SIZE,
-	    "IU", "Grcdump buffer");
+	    CTLFLAG_RD | CTLFLAG_SKIP, sc->grcdump_buffer,
+	    BXE_GRCDUMP_BUF_SIZE, "IU", "Access grcdump buffer");
 
 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "breakpoint",
-	    CTLTYPE_INT | CTLFLAG_RW, (void *)sc, 0, bxe_sysctl_breakpoint,
-	    "I", "Driver breakpoint");
+	    CTLTYPE_INT | CTLFLAG_RW, (void *)sc, 0,
+	    bxe_sysctl_breakpoint, "I", "Driver breakpoint");
 
 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "reg_read",
-	    CTLTYPE_INT | CTLFLAG_RW, (void *)sc, 0, bxe_sysctl_reg_read,
-	    "I", "Register read");
+	    CTLTYPE_INT | CTLFLAG_RW, (void *)sc, 0,
+	    bxe_sysctl_reg_read, "I", "Register read");
+
 #endif /* BXE_DEBUG */
 }
 
@@ -15886,7 +15939,7 @@ bxe_dump_debug_reg_wread(struct bxe_soft
  *   None.
  */
 static void
-bxe_dump_grc(struct bxe_softc *sc, int log)
+bxe_grcdump(struct bxe_softc *sc, int log)
 {
 	uint32_t *buf, i, index;
 

Modified: head/sys/dev/bxe/if_bxe.h
==============================================================================
--- head/sys/dev/bxe/if_bxe.h	Thu Mar 31 21:21:07 2011	(r220225)
+++ head/sys/dev/bxe/if_bxe.h	Thu Mar 31 21:30:00 2011	(r220226)
@@ -1084,6 +1084,8 @@ struct bxe_fastpath {
 
 	/* Memory buffer allocation failure counter. */
 	unsigned long		mbuf_alloc_failed;
+	unsigned long		mbuf_defrag_attempts;
+	unsigned long		mbuf_defrag_successes;
 
 	/* Track the number of enqueued mbufs. */
 	int			tx_mbuf_alloc;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201103312130.p2VLU0fG023271>