Index: bce/if_bce.c =================================================================== RCS file: /home/ncvs/src/sys/dev/bce/if_bce.c,v retrieving revision 1.2.2.19 diff -u -p -u -r1.2.2.19 if_bce.c --- bce/if_bce.c 14 Jul 2007 20:25:19 -0000 1.2.2.19 +++ bce/if_bce.c 1 Aug 2007 05:05:46 -0000 @@ -288,21 +288,22 @@ static int bce_blockinit (struct bce static int bce_get_buf (struct bce_softc *, struct mbuf *, u16 *, u16 *, u32 *); static int bce_init_tx_chain (struct bce_softc *); +static void bce_fill_rx_chain (struct bce_softc *); static int bce_init_rx_chain (struct bce_softc *); static void bce_free_rx_chain (struct bce_softc *); static void bce_free_tx_chain (struct bce_softc *); -static int bce_tx_encap (struct bce_softc *, struct mbuf **); +static int bce_tx_encap (struct bce_softc *, struct mbuf **); static void bce_start_locked (struct ifnet *); static void bce_start (struct ifnet *); static int bce_ioctl (struct ifnet *, u_long, caddr_t); static void bce_watchdog (struct bce_softc *); static int bce_ifmedia_upd (struct ifnet *); -static void bce_ifmedia_upd_locked (struct ifnet *); +static void bce_ifmedia_upd_locked (struct ifnet *); static void bce_ifmedia_sts (struct ifnet *, struct ifmediareq *); static void bce_init_locked (struct bce_softc *); static void bce_init (void *); -static void bce_mgmt_init_locked(struct bce_softc *sc); +static void bce_mgmt_init_locked (struct bce_softc *sc); static void bce_init_context (struct bce_softc *); static void bce_get_mac_addr (struct bce_softc *); @@ -623,7 +624,7 @@ bce_attach(device_t dev) if (val & BCE_PCICFG_MISC_STATUS_32BIT_DET) sc->bce_flags |= BCE_PCI_32BIT_FLAG; - /* Reset the controller and announce to bootcde that driver is present. */ + /* Reset the controller and announce to bootcode that driver is present. */ if (bce_reset(sc, BCE_DRV_MSG_CODE_RESET)) { BCE_PRINTF("%s(%d): Controller reset failed!\n", __FILE__, __LINE__); @@ -3160,7 +3161,7 @@ bce_stop(struct bce_softc *sc) bce_disable_intr(sc); - /* Free the RX lists. */ + /* Free RX buffers. */ bce_free_rx_chain(sc); /* Free TX buffers. */ @@ -3480,6 +3481,9 @@ bce_blockinit_exit: /* This routine will map an mbuf cluster into 1 or more rx_bd's as */ /* necessary. */ /* */ +/* Todo: Consider writing the hardware mailboxes here to make rx_bd's */ +/* available to the hardware as soon as possible. */ +/* */ /* Returns: */ /* 0 for success, positive value for failure. */ /****************************************************************************/ @@ -3487,10 +3491,10 @@ static int bce_get_buf(struct bce_softc *sc, struct mbuf *m, u16 *prod, u16 *chain_prod, u32 *prod_bseq) { - bus_dmamap_t map; - bus_dma_segment_t segs[4]; + bus_dmamap_t map; + bus_dma_segment_t segs[BCE_MAX_SEGMENTS]; struct mbuf *m_new = NULL; - struct rx_bd *rxbd; + struct rx_bd *rxbd; int i, nsegs, error, rc = 0; #ifdef BCE_DEBUG u16 debug_chain_prod = *chain_prod; @@ -3507,12 +3511,13 @@ bce_get_buf(struct bce_softc *sc, struct DBPRINT(sc, BCE_VERBOSE_RECV, "%s(enter): prod = 0x%04X, chain_prod = 0x%04X, " "prod_bseq = 0x%08X\n", __FUNCTION__, *prod, *chain_prod, *prod_bseq); + /* Check whether this is a new mbuf allocation. */ if (m == NULL) { + /* Simulate an mbuf allocation failure. */ DBRUNIF(DB_RANDOMTRUE(bce_debug_mbuf_allocation_failure), - BCE_PRINTF("%s(%d): Simulating mbuf allocation failure.\n", - __FILE__, __LINE__); - sc->mbuf_alloc_failed++; + sc->mbuf_alloc_failed++; + sc->mbuf_sim_alloc_failed++; rc = ENOBUFS; goto bce_get_buf_exit); @@ -3523,13 +3528,24 @@ bce_get_buf(struct bce_softc *sc, struct DBPRINT(sc, BCE_WARN, "%s(%d): RX mbuf header allocation failed!\n", __FILE__, __LINE__); - DBRUNIF(1, sc->mbuf_alloc_failed++); + sc->mbuf_alloc_failed++; rc = ENOBUFS; goto bce_get_buf_exit; } DBRUNIF(1, sc->rx_mbuf_alloc++); + + /* Simulate an mbuf cluster allocation failure. */ + DBRUNIF(DB_RANDOMTRUE(bce_debug_mbuf_allocation_failure), + m_freem(m_new); + sc->rx_mbuf_alloc--; + sc->mbuf_alloc_failed++; + sc->mbuf_sim_alloc_failed++; + rc = ENOBUFS; + goto bce_get_buf_exit); + + /* Attach a cluster to the mbuf. */ m_cljget(m_new, M_DONTWAIT, sc->mbuf_alloc_size); if (!(m_new->m_flags & M_EXT)) { @@ -3537,16 +3553,17 @@ bce_get_buf(struct bce_softc *sc, struct __FILE__, __LINE__); m_freem(m_new); - DBRUNIF(1, sc->rx_mbuf_alloc--); - DBRUNIF(1, sc->mbuf_alloc_failed++); + sc->mbuf_alloc_failed++; rc = ENOBUFS; goto bce_get_buf_exit; } + /* Initialize the mbuf cluster. */ m_new->m_len = m_new->m_pkthdr.len = sc->mbuf_alloc_size; } else { + /* Reuse an existing mbuf. */ m_new = m; m_new->m_len = m_new->m_pkthdr.len = sc->mbuf_alloc_size; m_new->m_data = m_new->m_ext.ext_buf; @@ -3557,27 +3574,38 @@ bce_get_buf(struct bce_softc *sc, struct error = bus_dmamap_load_mbuf_sg(sc->rx_mbuf_tag, map, m_new, segs, &nsegs, BUS_DMA_NOWAIT); + /* Handle any mapping errors. */ if (error) { BCE_PRINTF("%s(%d): Error mapping mbuf into RX chain!\n", __FILE__, __LINE__); m_freem(m_new); - DBRUNIF(1, sc->rx_mbuf_alloc--); rc = ENOBUFS; goto bce_get_buf_exit; } - /* Watch for overflow. */ - DBRUNIF((sc->free_rx_bd > USABLE_RX_BD), - BCE_PRINTF("%s(%d): Too many free rx_bd (0x%04X > 0x%04X)!\n", - __FILE__, __LINE__, sc->free_rx_bd, (u16) USABLE_RX_BD)); + /* Make sure there is room in the receive chain. */ + if (nsegs > sc->free_rx_bd) { + bus_dmamap_unload(sc->rx_mbuf_tag, map); + + m_freem(m_new); + DBRUNIF(1, sc->rx_mbuf_alloc--); + + rc = EFBIG; + goto bce_get_buf_exit; + } + +#ifdef BCE_DEBUG + /* Track the distribution of buffer segments. */ + sc->rx_mbuf_segs[nsegs]++; +#endif /* Update some debug statistic counters */ DBRUNIF((sc->free_rx_bd < sc->rx_low_watermark), sc->rx_low_watermark = sc->free_rx_bd); - DBRUNIF((sc->free_rx_bd == 0), sc->rx_empty_count++); + DBRUNIF((sc->free_rx_bd == sc->max_rx_bd), sc->rx_empty_count++); /* Setup the rx_bd for the first segment. */ rxbd = &sc->rx_bd_chain[RX_PAGE(*chain_prod)][RX_IDX(*chain_prod)]; @@ -3723,6 +3751,8 @@ bce_free_tx_chain(struct bce_softc *sc) for (i = 0; i < TX_PAGES; i++) bzero((char *)sc->tx_bd_chain[i], BCE_TX_CHAIN_PAGE_SZ); + sc->used_tx_bd = 0; + /* Check if we lost any mbufs in the process. */ DBRUNIF((sc->tx_mbuf_alloc), BCE_PRINTF("%s(%d): Memory leak! Lost %d mbufs " @@ -3734,6 +3764,62 @@ bce_free_tx_chain(struct bce_softc *sc) /****************************************************************************/ +/* Add mbufs to the RX chain until its full or an mbuf allocation error */ +/* occurs. */ +/* */ +/* Returns: */ +/* Nothing */ +/****************************************************************************/ +static void +bce_fill_rx_chain(struct bce_softc *sc) +{ + u16 prod, chain_prod; + u32 prod_bseq; +#ifdef BCE_DEBUG + int rx_mbuf_alloc_before, free_rx_bd_before; +#endif + + DBPRINT(sc, BCE_EXCESSIVE_RECV, "Entering %s()\n", __FUNCTION__); + + prod = sc->rx_prod; + prod_bseq = sc->rx_prod_bseq; + +#ifdef BCE_DEBUG + rx_mbuf_alloc_before = sc->rx_mbuf_alloc; + free_rx_bd_before = sc->free_rx_bd; +#endif + + /* Keep filling the RX chain until it's full. */ + while (sc->free_rx_bd > 0) { + chain_prod = RX_CHAIN_IDX(prod); + if (bce_get_buf(sc, NULL, &prod, &chain_prod, &prod_bseq)) { + /* Bail out if we can't add an mbuf to the chain. */ + break; + } + prod = NEXT_RX_BD(prod); + } + +#if 0 + DBRUNIF((sc->rx_mbuf_alloc - rx_mbuf_alloc_before), + BCE_PRINTF("%s(): Installed %d mbufs in %d rx_bd entries.\n", + __FUNCTION__, (sc->rx_mbuf_alloc - rx_mbuf_alloc_before), + (free_rx_bd_before - sc->free_rx_bd))); +#endif + + /* Save the RX chain producer index. */ + sc->rx_prod = prod; + sc->rx_prod_bseq = prod_bseq; + + /* Tell the chip about the waiting rx_bd's. */ + REG_WR16(sc, MB_RX_CID_ADDR + BCE_L2CTX_HOST_BDIDX, sc->rx_prod); + REG_WR(sc, MB_RX_CID_ADDR + BCE_L2CTX_HOST_BSEQ, sc->rx_prod_bseq); + + DBPRINT(sc, BCE_EXCESSIVE_RECV, "Exiting %s()\n", __FUNCTION__); + +} + + +/****************************************************************************/ /* Allocate memory and initialize the RX data structures. */ /* */ /* Returns: */ @@ -3744,8 +3830,7 @@ bce_init_rx_chain(struct bce_softc *sc) { struct rx_bd *rxbd; int i, rc = 0; - u16 prod, chain_prod; - u32 prod_bseq, val; + u32 val; DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__); @@ -3787,22 +3872,10 @@ bce_init_rx_chain(struct bce_softc *sc) val = BCE_ADDR_LO(sc->rx_bd_chain_paddr[0]); CTX_WR(sc, GET_CID_ADDR(RX_CID), BCE_L2CTX_NX_BDHADDR_LO, val); - /* Allocate mbuf clusters for the rx_bd chain. */ - prod = prod_bseq = 0; - while (prod < TOTAL_RX_BD) { - chain_prod = RX_CHAIN_IDX(prod); - if (bce_get_buf(sc, NULL, &prod, &chain_prod, &prod_bseq)) { - BCE_PRINTF("%s(%d): Error filling RX chain: rx_bd[0x%04X]!\n", - __FILE__, __LINE__, chain_prod); - rc = ENOBUFS; - break; - } - prod = NEXT_RX_BD(prod); - } - /* Save the RX chain producer index. */ - sc->rx_prod = prod; - sc->rx_prod_bseq = prod_bseq; + /* Fill up the RX chain. */ + bce_fill_rx_chain(sc); + for (i = 0; i < RX_PAGES; i++) { bus_dmamap_sync( @@ -3811,10 +3884,6 @@ bce_init_rx_chain(struct bce_softc *sc) BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); } - /* Tell the chip about the waiting rx_bd's. */ - REG_WR16(sc, MB_RX_CID_ADDR + BCE_L2CTX_HOST_BDIDX, sc->rx_prod); - REG_WR(sc, MB_RX_CID_ADDR + BCE_L2CTX_HOST_BSEQ, sc->rx_prod_bseq); - DBRUN(BCE_VERBOSE_RECV, bce_dump_rx_chain(sc, 0, TOTAL_RX_BD)); DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__); @@ -3833,9 +3902,16 @@ static void bce_free_rx_chain(struct bce_softc *sc) { int i; +#ifdef BCE_DEBUG + int rx_mbuf_alloc_before; +#endif DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__); +#ifdef BCE_DEBUG + rx_mbuf_alloc_before = sc->rx_mbuf_alloc; +#endif + /* Free any mbufs still in the RX mbuf chain. */ for (i = 0; i < TOTAL_RX_BD; i++) { if (sc->rx_mbuf_ptr[i] != NULL) { @@ -3848,10 +3924,16 @@ bce_free_rx_chain(struct bce_softc *sc) } } + DBRUNIF((rx_mbuf_alloc_before - sc->rx_mbuf_alloc), + BCE_PRINTF("%s(): Released %d mbufs.\n", + __FUNCTION__, (rx_mbuf_alloc_before - sc->rx_mbuf_alloc))); + /* Clear each RX chain page. */ for (i = 0; i < RX_PAGES; i++) bzero((char *)sc->rx_bd_chain[i], BCE_RX_CHAIN_PAGE_SZ); + sc->free_rx_bd = sc->max_rx_bd; + /* Check if we lost any mbufs in the process. */ DBRUNIF((sc->rx_mbuf_alloc), BCE_PRINTF("%s(%d): Memory leak! Lost %d mbufs from rx chain!\n", @@ -4017,8 +4099,7 @@ bce_rx_intr(struct bce_softc *sc) DBPRINT(sc, BCE_INFO_RECV, "%s(enter): sw_prod = 0x%04X, " "sw_cons = 0x%04X, sw_prod_bseq = 0x%08X\n", - __FUNCTION__, sw_prod, sw_cons, - sw_prod_bseq); + __FUNCTION__, sw_prod, sw_cons, sw_prod_bseq); /* Prevent speculative reads from getting ahead of the status block. */ bus_space_barrier(sc->bce_btag, sc->bce_bhandle, 0, 0, @@ -4027,7 +4108,7 @@ bce_rx_intr(struct bce_softc *sc) /* Update some debug statistics counters */ DBRUNIF((sc->free_rx_bd < sc->rx_low_watermark), sc->rx_low_watermark = sc->free_rx_bd); - DBRUNIF((sc->free_rx_bd == 0), sc->rx_empty_count++); + DBRUNIF((sc->free_rx_bd == USABLE_RX_BD), sc->rx_empty_count++); /* Scan through the receive chain as long as there is work to do */ while (sw_cons != hw_cons) { @@ -4082,7 +4163,7 @@ bce_rx_intr(struct bce_softc *sc) bus_dmamap_unload(sc->rx_mbuf_tag, sc->rx_mbuf_map[sw_chain_cons]); - /* Remove the mbuf from the driver's chain. */ + /* Remove the mbuf from the RX chain. */ m = sc->rx_mbuf_ptr[sw_chain_cons]; sc->rx_mbuf_ptr[sw_chain_cons] = NULL; @@ -4120,41 +4201,14 @@ bce_rx_intr(struct bce_softc *sc) L2_FHDR_ERRORS_PHY_DECODE | L2_FHDR_ERRORS_ALIGNMENT | L2_FHDR_ERRORS_TOO_SHORT | L2_FHDR_ERRORS_GIANT_FRAME)) { + /* Log the error and release the mbuf. */ ifp->if_ierrors++; DBRUNIF(1, sc->l2fhdr_status_errors++); + + /* Todo: Reuse the mbuf to improve performance. */ - /* Reuse the mbuf for a new frame. */ - if (bce_get_buf(sc, m, &sw_prod, &sw_chain_prod, &sw_prod_bseq)) { - - DBRUNIF(1, bce_breakpoint(sc)); - panic("bce%d: Can't reuse RX mbuf!\n", sc->bce_unit); - - } - goto bce_rx_int_next_rx; - } - - /* - * Get a new mbuf for the rx_bd. If no new - * mbufs are available then reuse the current mbuf, - * log an ierror on the interface, and generate - * an error in the system log. - */ - if (bce_get_buf(sc, NULL, &sw_prod, &sw_chain_prod, &sw_prod_bseq)) { - - DBRUN(BCE_WARN, - BCE_PRINTF("%s(%d): Failed to allocate " - "new mbuf, incoming frame dropped!\n", - __FILE__, __LINE__)); - - ifp->if_ierrors++; - - /* Try and reuse the exisitng mbuf. */ - if (bce_get_buf(sc, m, &sw_prod, &sw_chain_prod, &sw_prod_bseq)) { - - DBRUNIF(1, bce_breakpoint(sc)); - panic("bce%d: Double mbuf allocation failure!", sc->bce_unit); - - } + m_freem(m); + m = NULL; goto bce_rx_int_next_rx; } @@ -4237,8 +4291,6 @@ bce_rx_int_next_rx: if (m) { /* Make sure we don't lose our place when we release the lock. */ sc->rx_cons = sw_cons; - sc->rx_prod = sw_prod; - sc->rx_prod_bseq = sw_prod_bseq; DBPRINT(sc, BCE_VERBOSE_RECV, "%s(): Passing received frame up.\n", __FUNCTION__); @@ -4249,11 +4301,6 @@ bce_rx_int_next_rx: /* Recover our place. */ sw_cons = sc->rx_cons; - sw_prod = sc->rx_prod; - sw_prod_bseq = sc->rx_prod_bseq; - hw_cons = sc->hw_rx_cons = sblk->status_rx_quick_consumer_index0; - if ((hw_cons & USABLE_RX_BD_PER_PAGE) == USABLE_RX_BD_PER_PAGE) - hw_cons++; } /* Refresh hw_cons to see if there's new work */ @@ -4268,17 +4315,14 @@ bce_rx_int_next_rx: BUS_SPACE_BARRIER_READ); } + /* No new packets to process. Refill the RX chain and exit. */ + sc->rx_cons = sw_cons; + bce_fill_rx_chain(sc); + for (int i = 0; i < RX_PAGES; i++) bus_dmamap_sync(sc->rx_bd_chain_tag, sc->rx_bd_chain_map[i], BUS_DMASYNC_PREWRITE); - sc->rx_cons = sw_cons; - sc->rx_prod = sw_prod; - sc->rx_prod_bseq = sw_prod_bseq; - - REG_WR16(sc, MB_RX_CID_ADDR + BCE_L2CTX_HOST_BDIDX, sc->rx_prod); - REG_WR(sc, MB_RX_CID_ADDR + BCE_L2CTX_HOST_BSEQ, sc->rx_prod_bseq); - DBPRINT(sc, BCE_INFO_RECV, "%s(exit): rx_prod = 0x%04X, " "rx_cons = 0x%04X, rx_prod_bseq = 0x%08X\n", __FUNCTION__, sc->rx_prod, sc->rx_cons, sc->rx_prod_bseq); @@ -4612,6 +4656,8 @@ bce_init(void *xsc) /* */ /* Returns: */ /* 0 for success, positive value for failure. */ +/* Modified: */ +/* m_head: May be set to NULL if MBUF is excessively fragmented. */ /****************************************************************************/ static int bce_tx_encap(struct bce_softc *sc, struct mbuf **m_head) @@ -4658,16 +4704,18 @@ bce_tx_encap(struct bce_softc *sc, struc /* Check if the DMA mapping was successful */ if (error == EFBIG) { - DBPRINT(sc, BCE_WARN, "%s(): fragmented mbuf (%d pieces)\n", + /* The mbuf is too fragmented for our DMA mapping. */ + DBPRINT(sc, BCE_WARN, "%s(): fragmented mbuf (%d pieces)\n", __FUNCTION__, nsegs); DBRUNIF(1, bce_dump_mbuf(sc, m0);); - /* Try to defrag the mbuf if there are too many segments. */ + /* Try to defrag the mbuf. */ m0 = m_defrag(*m_head, M_DONTWAIT); - if (m0 == NULL) { + if (m0 == NULL) { /* Defrag was unsuccessful */ m_freem(*m_head); *m_head = NULL; + sc->mbuf_alloc_failed++; return (ENOBUFS); } @@ -4678,20 +4726,27 @@ bce_tx_encap(struct bce_softc *sc, struc /* Still getting an error after a defrag. */ if (error == ENOMEM) { + /* Insufficient DMA buffers available. */ + sc->tx_dma_map_failures++; return (error); } else if (error != 0) { + /* Still can't map the mbuf, release it and return an error. */ BCE_PRINTF( "%s(%d): Unknown error mapping mbuf into TX chain!\n", __FILE__, __LINE__); m_freem(m0); *m_head = NULL; + sc->tx_dma_map_failures++; return (ENOBUFS); } } else if (error == ENOMEM) { + /* Insufficient DMA buffers available. */ + sc->tx_dma_map_failures++; return (error); } else if (error != 0) { m_freem(m0); *m_head = NULL; + sc->tx_dma_map_failures++; return (error); } @@ -4820,7 +4875,8 @@ bce_start_locked(struct ifnet *ifp) * to wait for the NIC to drain the chain. */ if (bce_tx_encap(sc, &m_head)) { - IFQ_DRV_PREPEND(&ifp->if_snd, m_head); + if (m_head != NULL) + IFQ_DRV_PREPEND(&ifp->if_snd, m_head); ifp->if_drv_flags |= IFF_DRV_OACTIVE; DBPRINT(sc, BCE_INFO_SEND, "TX chain is closed for business! Total tx_bd used = %d\n", @@ -5792,7 +5848,7 @@ bce_sysctl_dump_rx_chain(SYSCTL_HANDLER_ if (result == 1) { sc = (struct bce_softc *)arg1; - bce_dump_rx_chain(sc, 0, USABLE_RX_BD); + bce_dump_rx_chain(sc, 0, sc->max_rx_bd); } return error; @@ -5974,10 +6030,61 @@ bce_add_sysctls(struct bce_softc *sc) 0, "lost status block updates"); SYSCTL_ADD_INT(ctx, children, OID_AUTO, + "mbuf_sim_alloc_failed", + CTLFLAG_RD, &sc->mbuf_sim_alloc_failed, + 0, "mbuf cluster simulated allocation failures"); + + SYSCTL_ADD_INT(ctx, children, OID_AUTO, + "rx_mbuf_segs[1]", + CTLFLAG_RD, &sc->rx_mbuf_segs[1], + 0, "mbuf cluster with 1 segment"); + + SYSCTL_ADD_INT(ctx, children, OID_AUTO, + "rx_mbuf_segs[2]", + CTLFLAG_RD, &sc->rx_mbuf_segs[2], + 0, "mbuf cluster with 2 segments"); + + SYSCTL_ADD_INT(ctx, children, OID_AUTO, + "rx_mbuf_segs[3]", + CTLFLAG_RD, &sc->rx_mbuf_segs[3], + 0, "mbuf cluster with 3 segments"); + + SYSCTL_ADD_INT(ctx, children, OID_AUTO, + "rx_mbuf_segs[4]", + CTLFLAG_RD, &sc->rx_mbuf_segs[4], + 0, "mbuf cluster with 4 segments"); + + SYSCTL_ADD_INT(ctx, children, OID_AUTO, + "rx_mbuf_segs[5]", + CTLFLAG_RD, &sc->rx_mbuf_segs[5], + 0, "mbuf cluster with 5 segments"); + + SYSCTL_ADD_INT(ctx, children, OID_AUTO, + "rx_mbuf_segs[6]", + CTLFLAG_RD, &sc->rx_mbuf_segs[6], + 0, "mbuf cluster with 6 segments"); + + SYSCTL_ADD_INT(ctx, children, OID_AUTO, + "rx_mbuf_segs[7]", + CTLFLAG_RD, &sc->rx_mbuf_segs[7], + 0, "mbuf cluster with 7 segments"); + + SYSCTL_ADD_INT(ctx, children, OID_AUTO, + "rx_mbuf_segs[8]", + CTLFLAG_RD, &sc->rx_mbuf_segs[8], + 0, "mbuf cluster with 8 segments"); + +#endif + + SYSCTL_ADD_INT(ctx, children, OID_AUTO, "mbuf_alloc_failed", CTLFLAG_RD, &sc->mbuf_alloc_failed, 0, "mbuf cluster allocation failures"); -#endif + + SYSCTL_ADD_INT(ctx, children, OID_AUTO, + "tx_dma_map_failures", + CTLFLAG_RD, &sc->tx_dma_map_failures, + 0, "tx dma mapping failures"); SYSCTL_ADD_ULONG(ctx, children, OID_AUTO, "stat_IfHcInOctets", @@ -7159,6 +7266,15 @@ bce_dump_driver_state(struct bce_softc * BCE_PRINTF(" 0x%08X - (sc->tx_prod_bseq) tx producer bseq index\n", sc->tx_prod_bseq); + BCE_PRINTF(" 0x%08X - (sc->tx_mbuf_alloc) tx mbufs allocated\n", + sc->tx_mbuf_alloc); + + BCE_PRINTF(" 0x%08X - (sc->used_tx_bd) used tx_bd's\n", + sc->used_tx_bd); + + BCE_PRINTF("0x%08X/%08X - (sc->tx_hi_watermark) tx hi watermark\n", + sc->tx_hi_watermark, sc->max_tx_bd); + BCE_PRINTF(" 0x%04X(0x%04X) - (sc->rx_prod) rx producer index\n", sc->rx_prod, (u16) RX_CHAIN_IDX(sc->rx_prod)); @@ -7177,21 +7293,14 @@ bce_dump_driver_state(struct bce_softc * BCE_PRINTF("0x%08X/%08X - (sc->rx_low_watermark) rx low watermark\n", sc->rx_low_watermark, sc->max_rx_bd); - BCE_PRINTF(" 0x%08X - (sc->txmbuf_alloc) tx mbufs allocated\n", - sc->tx_mbuf_alloc); - - BCE_PRINTF(" 0x%08X - (sc->rx_mbuf_alloc) rx mbufs allocated\n", - sc->rx_mbuf_alloc); - - BCE_PRINTF(" 0x%08X - (sc->used_tx_bd) used tx_bd's\n", - sc->used_tx_bd); - - BCE_PRINTF("0x%08X/%08X - (sc->tx_hi_watermark) tx hi watermark\n", - sc->tx_hi_watermark, sc->max_tx_bd); - - BCE_PRINTF(" 0x%08X - (sc->mbuf_alloc_failed) failed mbuf alloc\n", + BCE_PRINTF(" 0x%08X - (sc->mbuf_alloc_failed) " + "mbuf alloc failures\n", sc->mbuf_alloc_failed); + BCE_PRINTF(" 0x%08X - (sc->mbuf_sim_alloc_failed) " + "simulated mbuf alloc failures\n", + sc->mbuf_sim_alloc_failed); + BCE_PRINTF( "----------------------------" "----------------" @@ -7476,10 +7585,10 @@ bce_breakpoint(struct bce_softc *sc) bce_dump_txbd(sc, 0, NULL); bce_dump_rxbd(sc, 0, NULL); bce_dump_tx_mbuf_chain(sc, 0, USABLE_TX_BD); - bce_dump_rx_mbuf_chain(sc, 0, USABLE_RX_BD); + bce_dump_rx_mbuf_chain(sc, 0, sc->max_rx_bd); bce_dump_l2fhdr(sc, 0, NULL); bce_dump_tx_chain(sc, 0, USABLE_TX_BD); - bce_dump_rx_chain(sc, 0, USABLE_RX_BD); + bce_dump_rx_chain(sc, 0, sc->max_rx_bd); bce_dump_status_block(sc); bce_dump_stats_block(sc); bce_dump_driver_state(sc); Index: bce/if_bcereg.h =================================================================== RCS file: /home/ncvs/src/sys/dev/bce/if_bcereg.h,v retrieving revision 1.1.2.7 diff -u -p -u -r1.1.2.7 if_bcereg.h --- bce/if_bcereg.h 14 Jun 2007 21:28:14 -0000 1.1.2.7 +++ bce/if_bcereg.h 1 Aug 2007 05:02:31 -0000 @@ -487,6 +487,9 @@ struct flash_spec { #define BCE_DRV_PULSE_MB 0x00000010 #define BCE_DRV_PULSE_SEQ_MASK 0x00007fff +#define BCE_MB_ARGS_0 0x00000014 +#define BCE_MB_ARGS_1 0x00000018 + /* Indicate to the firmware not to go into the * OS absent when it is not getting driver pulse. * This is used for debugging. */ @@ -4918,11 +4921,21 @@ struct bce_softc /* Provides access to certain firmware statistics. */ u32 com_no_buffers; + + /* Mbuf allocation failure counter. */ + u32 mbuf_alloc_failed; + + /* TX DMA mapping failure counter. */ + u32 tx_dma_map_failures; + #ifdef BCE_DEBUG /* Track the number of enqueued mbufs. */ int tx_mbuf_alloc; int rx_mbuf_alloc; + /* Track the distribution buffer segments. */ + u32 rx_mbuf_segs[BCE_MAX_SEGMENTS+1]; + /* Track how many and what type of interrupts are generated. */ u32 interrupts_generated; u32 interrupts_handled; @@ -4933,7 +4946,7 @@ struct bce_softc u32 rx_empty_count; /* Number of times the RX chain was empty. */ u32 tx_hi_watermark; /* Greatest number of tx_bd's used. */ u32 tx_full_count; /* Number of times the TX chain was full. */ - u32 mbuf_alloc_failed; /* Mbuf allocation failure counter. */ + u32 mbuf_sim_alloc_failed; /* Mbuf simulated allocation failure counter. */ u32 l2fhdr_status_errors; u32 unexpected_attentions; u32 lost_status_block_updates;