Index: src/sys/dev/bce/if_bce.c diff -u src/sys/dev/bce/if_bce.c:1.2.4.2 src/sys/dev/bce/if_bce.c:1.2.2.5 --- src/sys/dev/bce/if_bce.c:1.2.4.2 Thu Apr 13 22:42:07 2006 +++ src/sys/dev/bce/if_bce.c Mon Jul 31 18:53:09 2006 @@ -53,7 +53,7 @@ /****************************************************************************/ /* BCE Driver Version */ /****************************************************************************/ -char bce_driver_version[] = "v0.9.5"; +char bce_driver_version[] = "v0.9.6"; /****************************************************************************/ @@ -4640,10 +4640,32 @@ bce_dma_map_tx_desc, &map_arg, BUS_DMA_NOWAIT); if (error || map_arg.maxsegs == 0) { - BCE_PRINTF(sc, "%s(%d): Error mapping mbuf into TX chain!\n", - __FILE__, __LINE__); - rc = ENOBUFS; - goto bce_tx_encap_exit; + + /* Try to defrag the mbuf if there are too many segments. */ + if (error == EFBIG && map_arg.maxsegs != 0) { + struct mbuf *m0; + + DBPRINT(sc, BCE_WARN, "%s(): fragmented mbuf (%d pieces)\n", + __FUNCTION__, map_arg.maxsegs); + + m0 = m_defrag(m_head, M_DONTWAIT); + if (m0 != NULL) { + m_head = m0; + error = bus_dmamap_load_mbuf(sc->tx_mbuf_tag, + map, m_head, bce_dma_map_tx_desc, &map_arg, + BUS_DMA_NOWAIT); + } + } + + /* Still getting an error after a defrag. */ + if (error) { + BCE_PRINTF(sc, + "%s(%d): Error mapping mbuf into TX chain!\n", + __FILE__, __LINE__); + rc = ENOBUFS; + goto bce_tx_encap_exit; + } + } /* @@ -4818,9 +4840,11 @@ DBPRINT(sc, BCE_INFO, "Setting new MTU of %d\n", ifr->ifr_mtu); + BCE_LOCK(sc); ifp->if_mtu = ifr->ifr_mtu; ifp->if_drv_flags &= ~IFF_DRV_RUNNING; - bce_init(sc); + bce_init_locked(sc); + BCE_UNLOCK(sc); break; /* Set interface. */ @@ -4831,8 +4855,13 @@ /* Check if the interface is up. */ if (ifp->if_flags & IFF_UP) { - /* Change the promiscuous/multicast flags as necessary. */ - bce_set_rx_mode(sc); + if (ifp->if_drv_flags & IFF_DRV_RUNNING) { + /* Change the promiscuous/multicast flags as necessary. */ + bce_set_rx_mode(sc); + } else { + /* Start the HW */ + bce_init_locked(sc); + } } else { /* The interface is down. Check if the driver is running. */ if (ifp->if_drv_flags & IFF_DRV_RUNNING) { @@ -4850,12 +4879,12 @@ case SIOCDELMULTI: DBPRINT(sc, BCE_VERBOSE, "Received SIOCADDMULTI/SIOCDELMULTI\n"); + BCE_LOCK(sc); if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - BCE_LOCK(sc); bce_set_rx_mode(sc); - BCE_UNLOCK(sc); error = 0; } + BCE_UNLOCK(sc); break; @@ -5004,10 +5033,12 @@ /* DBRUN(BCE_FATAL, bce_breakpoint(sc)); */ + BCE_LOCK(sc); ifp->if_drv_flags &= ~IFF_DRV_RUNNING; - bce_init(sc); + bce_init_locked(sc); ifp->if_oerrors++; + BCE_UNLOCK(sc); } @@ -5308,14 +5339,6 @@ */ ifp->if_collisions = (u_long) stats->stat_EtherStatsCollisions; - ifp->if_ibytes = BCE_STATS(IfHCInOctets); - - ifp->if_obytes = BCE_STATS(IfHCOutOctets); - - ifp->if_imcasts = BCE_STATS(IfHCInMulticastPkts); - - ifp->if_omcasts = BCE_STATS(IfHCOutMulticastPkts); - ifp->if_ierrors = (u_long) stats->stat_EtherStatsUndersizePkts + (u_long) stats->stat_EtherStatsOverrsizePkts + (u_long) stats->stat_IfInMBUFDiscards +