From owner-svn-src-head@FreeBSD.ORG Thu Mar 31 21:30:00 2011 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8A06B1065670; Thu, 31 Mar 2011 21:30:00 +0000 (UTC) (envelope-from davidch@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 7237B8FC12; Thu, 31 Mar 2011 21:30:00 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id p2VLU0ii023274; Thu, 31 Mar 2011 21:30:00 GMT (envelope-from davidch@svn.freebsd.org) Received: (from davidch@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id p2VLU0fG023271; Thu, 31 Mar 2011 21:30:00 GMT (envelope-from davidch@svn.freebsd.org) Message-Id: <201103312130.p2VLU0fG023271@svn.freebsd.org> From: David Christensen Date: Thu, 31 Mar 2011 21:30:00 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r220226 - head/sys/dev/bxe X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 31 Mar 2011 21:30:00 -0000 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;