Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 6 Jan 2010 22:45:49 +0000 (UTC)
From:      Pyun YongHyeon <yongari@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r201685 - stable/8/sys/dev/bge
Message-ID:  <201001062245.o06Mjn4T062532@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: yongari
Date: Wed Jan  6 22:45:49 2010
New Revision: 201685
URL: http://svn.freebsd.org/changeset/base/201685

Log:
  MFC r198923-198924,198927-198928
  
  r198923:
    Use correct dma tag for jumbo buffer.
  
  r198924:
    Covert bge_newbuf_std to use bus_dmamap_load_mbuf_sg(9). Note,
    bge_newbuf_std still has a bug for handling dma map load failure
    under high network load. Just reusing mbuf is not enough as driver
    already unloaded the dma map of the mbuf. Graceful recovery needs
    more work.
    Ideally we can just update dma address part of a Rx descriptor
    because the controller never overwrite the Rx descriptor. This
    requires some Rx initialization code changes and it would be done
    later after fixing other incorrect bus_dma(9) usages.
  
  r198927:
    Remove common DMA tag used for TX/RX mbufs and create Tx DMA tag
    and Rx DMA tag separately. Previously it used a common mbuf DMA tag
    for both Tx and Rx path but Rx buffer(standard ring case) should
    have a single DMA segment and maximum buffer size of the segment
    should be less than or equal to MCLBYTES. This change also make it
    possible to add TSO with minor changes.
  
  r198928:
    Make bge_newbuf_std()/bge_newbuf_jumbo() returns actual error code
    for buffer allocation. If driver know we are out of Rx buffers let
    controller stop. This should fix panic when interface is run even
    if it had no configured Rx buffers.

Modified:
  stable/8/sys/dev/bge/if_bge.c
  stable/8/sys/dev/bge/if_bgereg.h
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)

Modified: stable/8/sys/dev/bge/if_bge.c
==============================================================================
--- stable/8/sys/dev/bge/if_bge.c	Wed Jan  6 22:39:40 2010	(r201684)
+++ stable/8/sys/dev/bge/if_bge.c	Wed Jan  6 22:45:49 2010	(r201685)
@@ -916,8 +916,8 @@ bge_newbuf_std(struct bge_softc *sc, int
 {
 	struct mbuf *m_new = NULL;
 	struct bge_rx_bd *r;
-	struct bge_dmamap_arg ctx;
-	int error;
+	bus_dma_segment_t segs[1];
+	int error, nsegs;
 
 	if (m == NULL) {
 		m_new = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
@@ -932,27 +932,24 @@ bge_newbuf_std(struct bge_softc *sc, int
 
 	if ((sc->bge_flags & BGE_FLAG_RX_ALIGNBUG) == 0)
 		m_adj(m_new, ETHER_ALIGN);
-	sc->bge_cdata.bge_rx_std_chain[i] = m_new;
-	r = &sc->bge_ldata.bge_rx_std_ring[i];
-	ctx.bge_maxsegs = 1;
-	ctx.sc = sc;
-	error = bus_dmamap_load(sc->bge_cdata.bge_mtag,
-	    sc->bge_cdata.bge_rx_std_dmamap[i], mtod(m_new, void *),
-	    m_new->m_len, bge_dma_map_addr, &ctx, BUS_DMA_NOWAIT);
-	if (error || ctx.bge_maxsegs == 0) {
+	error = bus_dmamap_load_mbuf_sg(sc->bge_cdata.bge_rx_mtag,
+	    sc->bge_cdata.bge_rx_std_dmamap[i], m_new, segs, &nsegs, 0);
+	if (error != 0) {
 		if (m == NULL) {
 			sc->bge_cdata.bge_rx_std_chain[i] = NULL;
 			m_freem(m_new);
 		}
-		return (ENOMEM);
+		return (error);
 	}
-	r->bge_addr.bge_addr_lo = BGE_ADDR_LO(ctx.bge_busaddr);
-	r->bge_addr.bge_addr_hi = BGE_ADDR_HI(ctx.bge_busaddr);
+	sc->bge_cdata.bge_rx_std_chain[i] = m_new;
+	r = &sc->bge_ldata.bge_rx_std_ring[i];
+	r->bge_addr.bge_addr_lo = BGE_ADDR_LO(segs[0].ds_addr);
+	r->bge_addr.bge_addr_hi = BGE_ADDR_HI(segs[0].ds_addr);
 	r->bge_flags = BGE_RXBDFLAG_END;
-	r->bge_len = m_new->m_len;
+	r->bge_len = segs[0].ds_len;
 	r->bge_idx = i;
 
-	bus_dmamap_sync(sc->bge_cdata.bge_mtag,
+	bus_dmamap_sync(sc->bge_cdata.bge_rx_mtag,
 	    sc->bge_cdata.bge_rx_std_dmamap[i],
 	    BUS_DMASYNC_PREREAD);
 
@@ -1031,7 +1028,7 @@ bge_newbuf_jumbo(struct bge_softc *sc, i
 		panic("%s: %d segments\n", __func__, nsegs);
 	}
 
-	bus_dmamap_sync(sc->bge_cdata.bge_mtag,
+	bus_dmamap_sync(sc->bge_cdata.bge_mtag_jumbo,
 	    sc->bge_cdata.bge_rx_jumbo_dmamap[i],
 	    BUS_DMASYNC_PREREAD);
 
@@ -1047,11 +1044,11 @@ bge_newbuf_jumbo(struct bge_softc *sc, i
 static int
 bge_init_rx_ring_std(struct bge_softc *sc)
 {
-	int i;
+	int error, i;
 
 	for (i = 0; i < BGE_SSLOTS; i++) {
-		if (bge_newbuf_std(sc, i, NULL) == ENOBUFS)
-			return (ENOBUFS);
+		if ((error = bge_newbuf_std(sc, i, NULL)) != 0)
+			return (error);
 	};
 
 	bus_dmamap_sync(sc->bge_cdata.bge_rx_std_ring_tag,
@@ -1071,10 +1068,10 @@ bge_free_rx_ring_std(struct bge_softc *s
 
 	for (i = 0; i < BGE_STD_RX_RING_CNT; i++) {
 		if (sc->bge_cdata.bge_rx_std_chain[i] != NULL) {
-			bus_dmamap_sync(sc->bge_cdata.bge_mtag,
+			bus_dmamap_sync(sc->bge_cdata.bge_rx_mtag,
 			    sc->bge_cdata.bge_rx_std_dmamap[i],
 			    BUS_DMASYNC_POSTREAD);
-			bus_dmamap_unload(sc->bge_cdata.bge_mtag,
+			bus_dmamap_unload(sc->bge_cdata.bge_rx_mtag,
 			    sc->bge_cdata.bge_rx_std_dmamap[i]);
 			m_freem(sc->bge_cdata.bge_rx_std_chain[i]);
 			sc->bge_cdata.bge_rx_std_chain[i] = NULL;
@@ -1088,11 +1085,11 @@ static int
 bge_init_rx_ring_jumbo(struct bge_softc *sc)
 {
 	struct bge_rcb *rcb;
-	int i;
+	int error, i;
 
 	for (i = 0; i < BGE_JUMBO_RX_RING_CNT; i++) {
-		if (bge_newbuf_jumbo(sc, i, NULL) == ENOBUFS)
-			return (ENOBUFS);
+		if ((error = bge_newbuf_jumbo(sc, i, NULL)) != 0)
+			return (error);
 	};
 
 	bus_dmamap_sync(sc->bge_cdata.bge_rx_jumbo_ring_tag,
@@ -1141,10 +1138,10 @@ bge_free_tx_ring(struct bge_softc *sc)
 
 	for (i = 0; i < BGE_TX_RING_CNT; i++) {
 		if (sc->bge_cdata.bge_tx_chain[i] != NULL) {
-			bus_dmamap_sync(sc->bge_cdata.bge_mtag,
+			bus_dmamap_sync(sc->bge_cdata.bge_tx_mtag,
 			    sc->bge_cdata.bge_tx_dmamap[i],
 			    BUS_DMASYNC_POSTWRITE);
-			bus_dmamap_unload(sc->bge_cdata.bge_mtag,
+			bus_dmamap_unload(sc->bge_cdata.bge_tx_mtag,
 			    sc->bge_cdata.bge_tx_dmamap[i]);
 			m_freem(sc->bge_cdata.bge_tx_chain[i]);
 			sc->bge_cdata.bge_tx_chain[i] = NULL;
@@ -1979,7 +1976,7 @@ bge_dma_free(struct bge_softc *sc)
 	/* Destroy DMA maps for RX buffers. */
 	for (i = 0; i < BGE_STD_RX_RING_CNT; i++) {
 		if (sc->bge_cdata.bge_rx_std_dmamap[i])
-			bus_dmamap_destroy(sc->bge_cdata.bge_mtag,
+			bus_dmamap_destroy(sc->bge_cdata.bge_rx_mtag,
 			    sc->bge_cdata.bge_rx_std_dmamap[i]);
 	}
 
@@ -1993,12 +1990,14 @@ bge_dma_free(struct bge_softc *sc)
 	/* Destroy DMA maps for TX buffers. */
 	for (i = 0; i < BGE_TX_RING_CNT; i++) {
 		if (sc->bge_cdata.bge_tx_dmamap[i])
-			bus_dmamap_destroy(sc->bge_cdata.bge_mtag,
+			bus_dmamap_destroy(sc->bge_cdata.bge_tx_mtag,
 			    sc->bge_cdata.bge_tx_dmamap[i]);
 	}
 
-	if (sc->bge_cdata.bge_mtag)
-		bus_dma_tag_destroy(sc->bge_cdata.bge_mtag);
+	if (sc->bge_cdata.bge_rx_mtag)
+		bus_dma_tag_destroy(sc->bge_cdata.bge_rx_mtag);
+	if (sc->bge_cdata.bge_tx_mtag)
+		bus_dma_tag_destroy(sc->bge_cdata.bge_tx_mtag);
 
 
 	/* Destroy standard RX ring. */
@@ -2109,21 +2108,33 @@ bge_dma_alloc(device_t dev)
 	}
 
 	/*
-	 * Create tag for mbufs.
+	 * Create tag for Tx mbufs.
 	 */
 	error = bus_dma_tag_create(sc->bge_cdata.bge_parent_tag, 1,
 	    0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL,
 	    NULL, MCLBYTES * BGE_NSEG_NEW, BGE_NSEG_NEW, MCLBYTES,
-	    BUS_DMA_ALLOCNOW, NULL, NULL, &sc->bge_cdata.bge_mtag);
+	    BUS_DMA_ALLOCNOW, NULL, NULL, &sc->bge_cdata.bge_tx_mtag);
 
 	if (error) {
-		device_printf(sc->bge_dev, "could not allocate dma tag\n");
+		device_printf(sc->bge_dev, "could not allocate TX dma tag\n");
+		return (ENOMEM);
+	}
+
+	/*
+	 * Create tag for Rx mbufs.
+	 */
+	error = bus_dma_tag_create(sc->bge_cdata.bge_parent_tag, 1, 0,
+	    BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, 1,
+	    MCLBYTES, BUS_DMA_ALLOCNOW, NULL, NULL, &sc->bge_cdata.bge_rx_mtag);
+
+	if (error) {
+		device_printf(sc->bge_dev, "could not allocate RX dma tag\n");
 		return (ENOMEM);
 	}
 
 	/* Create DMA maps for RX buffers. */
 	for (i = 0; i < BGE_STD_RX_RING_CNT; i++) {
-		error = bus_dmamap_create(sc->bge_cdata.bge_mtag, 0,
+		error = bus_dmamap_create(sc->bge_cdata.bge_rx_mtag, 0,
 			    &sc->bge_cdata.bge_rx_std_dmamap[i]);
 		if (error) {
 			device_printf(sc->bge_dev,
@@ -2134,11 +2145,11 @@ bge_dma_alloc(device_t dev)
 
 	/* Create DMA maps for TX buffers. */
 	for (i = 0; i < BGE_TX_RING_CNT; i++) {
-		error = bus_dmamap_create(sc->bge_cdata.bge_mtag, 0,
+		error = bus_dmamap_create(sc->bge_cdata.bge_tx_mtag, 0,
 			    &sc->bge_cdata.bge_tx_dmamap[i]);
 		if (error) {
 			device_printf(sc->bge_dev,
-			    "can't create DMA map for RX\n");
+			    "can't create DMA map for TX\n");
 			return (ENOMEM);
 		}
 	}
@@ -3168,18 +3179,17 @@ bge_rxeof(struct bge_softc *sc)
 				bge_newbuf_jumbo(sc, sc->bge_jumbo, m);
 				continue;
 			}
-			if (bge_newbuf_jumbo(sc,
-			    sc->bge_jumbo, NULL) == ENOBUFS) {
+			if (bge_newbuf_jumbo(sc, sc->bge_jumbo, NULL) != 0) {
 				ifp->if_ierrors++;
 				bge_newbuf_jumbo(sc, sc->bge_jumbo, m);
 				continue;
 			}
 		} else {
 			BGE_INC(sc->bge_std, BGE_STD_RX_RING_CNT);
-			bus_dmamap_sync(sc->bge_cdata.bge_mtag,
+			bus_dmamap_sync(sc->bge_cdata.bge_rx_mtag,
 			    sc->bge_cdata.bge_rx_std_dmamap[rxidx],
 			    BUS_DMASYNC_POSTREAD);
-			bus_dmamap_unload(sc->bge_cdata.bge_mtag,
+			bus_dmamap_unload(sc->bge_cdata.bge_rx_mtag,
 			    sc->bge_cdata.bge_rx_std_dmamap[rxidx]);
 			m = sc->bge_cdata.bge_rx_std_chain[rxidx];
 			sc->bge_cdata.bge_rx_std_chain[rxidx] = NULL;
@@ -3189,8 +3199,7 @@ bge_rxeof(struct bge_softc *sc)
 				bge_newbuf_std(sc, sc->bge_std, m);
 				continue;
 			}
-			if (bge_newbuf_std(sc, sc->bge_std,
-			    NULL) == ENOBUFS) {
+			if (bge_newbuf_std(sc, sc->bge_std, NULL) != 0) {
 				ifp->if_ierrors++;
 				bge_newbuf_std(sc, sc->bge_std, m);
 				continue;
@@ -3309,10 +3318,10 @@ bge_txeof(struct bge_softc *sc)
 		if (cur_tx->bge_flags & BGE_TXBDFLAG_END)
 			ifp->if_opackets++;
 		if (sc->bge_cdata.bge_tx_chain[idx] != NULL) {
-			bus_dmamap_sync(sc->bge_cdata.bge_mtag,
+			bus_dmamap_sync(sc->bge_cdata.bge_tx_mtag,
 			    sc->bge_cdata.bge_tx_dmamap[idx],
 			    BUS_DMASYNC_POSTWRITE);
-			bus_dmamap_unload(sc->bge_cdata.bge_mtag,
+			bus_dmamap_unload(sc->bge_cdata.bge_tx_mtag,
 			    sc->bge_cdata.bge_tx_dmamap[idx]);
 			m_freem(sc->bge_cdata.bge_tx_chain[idx]);
 			sc->bge_cdata.bge_tx_chain[idx] = NULL;
@@ -3645,7 +3654,7 @@ bge_encap(struct bge_softc *sc, struct m
 	}
 
 	map = sc->bge_cdata.bge_tx_dmamap[idx];
-	error = bus_dmamap_load_mbuf_sg(sc->bge_cdata.bge_mtag, map, m, segs,
+	error = bus_dmamap_load_mbuf_sg(sc->bge_cdata.bge_tx_mtag, map, m, segs,
 	    &nsegs, BUS_DMA_NOWAIT);
 	if (error == EFBIG) {
 		m = m_collapse(m, M_DONTWAIT, BGE_NSEG_NEW);
@@ -3655,8 +3664,8 @@ bge_encap(struct bge_softc *sc, struct m
 			return (ENOBUFS);
 		}
 		*m_head = m;
-		error = bus_dmamap_load_mbuf_sg(sc->bge_cdata.bge_mtag, map, m,
-		    segs, &nsegs, BUS_DMA_NOWAIT);
+		error = bus_dmamap_load_mbuf_sg(sc->bge_cdata.bge_tx_mtag, map,
+		    m, segs, &nsegs, BUS_DMA_NOWAIT);
 		if (error) {
 			m_freem(m);
 			*m_head = NULL;
@@ -3670,11 +3679,11 @@ bge_encap(struct bge_softc *sc, struct m
 	 * of the end of the ring.
 	 */
 	if (nsegs > (BGE_TX_RING_CNT - sc->bge_txcnt - 16)) {
-		bus_dmamap_unload(sc->bge_cdata.bge_mtag, map);
+		bus_dmamap_unload(sc->bge_cdata.bge_tx_mtag, map);
 		return (ENOBUFS);
 	}
 
-	bus_dmamap_sync(sc->bge_cdata.bge_mtag, map, BUS_DMASYNC_PREWRITE);
+	bus_dmamap_sync(sc->bge_cdata.bge_tx_mtag, map, BUS_DMASYNC_PREWRITE);
 
 	for (i = 0; ; i++) {
 		d = &sc->bge_ldata.bge_tx_ring[idx];
@@ -3886,7 +3895,11 @@ bge_init_locked(struct bge_softc *sc)
 	bge_setvlan(sc);
 
 	/* Init RX ring. */
-	bge_init_rx_ring_std(sc);
+	if (bge_init_rx_ring_std(sc) != 0) {
+		device_printf(sc->bge_dev, "no memory for std Rx buffers.\n");
+		bge_stop(sc);
+		return;
+	}
 
 	/*
 	 * Workaround for a bug in 5705 ASIC rev A0. Poll the NIC's
@@ -3907,8 +3920,13 @@ bge_init_locked(struct bge_softc *sc)
 	}
 
 	/* Init jumbo RX ring. */
-	if (ifp->if_mtu > (ETHERMTU + ETHER_HDR_LEN + ETHER_CRC_LEN))
-		bge_init_rx_ring_jumbo(sc);
+	if (ifp->if_mtu > (ETHERMTU + ETHER_HDR_LEN + ETHER_CRC_LEN)) {
+		if (bge_init_rx_ring_jumbo(sc) != 0) {
+			device_printf(sc->bge_dev, "no memory for std Rx buffers.\n");
+			bge_stop(sc);
+			return;
+		}
+	}
 
 	/* Init our RX return ring index. */
 	sc->bge_rx_saved_considx = 0;

Modified: stable/8/sys/dev/bge/if_bgereg.h
==============================================================================
--- stable/8/sys/dev/bge/if_bgereg.h	Wed Jan  6 22:39:40 2010	(r201684)
+++ stable/8/sys/dev/bge/if_bgereg.h	Wed Jan  6 22:45:49 2010	(r201685)
@@ -2543,8 +2543,9 @@ struct bge_chain_data {
 	bus_dma_tag_t		bge_tx_ring_tag;
 	bus_dma_tag_t		bge_status_tag;
 	bus_dma_tag_t		bge_stats_tag;
-	bus_dma_tag_t		bge_mtag;	/* mbuf mapping tag */
-	bus_dma_tag_t		bge_mtag_jumbo;	/* mbuf mapping tag */
+	bus_dma_tag_t		bge_rx_mtag;	/* Rx mbuf mapping tag */
+	bus_dma_tag_t		bge_tx_mtag;	/* Tx mbuf mapping tag */
+	bus_dma_tag_t		bge_mtag_jumbo;	/* Jumbo mbuf mapping tag */
 	bus_dmamap_t		bge_tx_dmamap[BGE_TX_RING_CNT];
 	bus_dmamap_t		bge_rx_std_dmamap[BGE_STD_RX_RING_CNT];
 	bus_dmamap_t		bge_rx_jumbo_dmamap[BGE_JUMBO_RX_RING_CNT];



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