[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openbsd-tech
Subject:    Improvements for bge(4)'s bge_encap() routine.
From:       Brad <brad () comstyle ! com>
Date:       2006-10-25 21:24:08
Message-ID: 20061025212408.GD13189 () blar ! home ! comstyle ! com
[Download RAW message or body]

The following patch moves the TX ring full sanity check further up
in the bge_encap() routine, since the driver knows how many DMA
segments it is trying to encapsulate, there is no reason to drop
down into the for loop and then break out of it later. In addition
to this I have fixed the routine to properly unmap the DMA map if
encountering an error.

Please test with any bge(4) interfaces and provide a dmesg.


Index: if_bge.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_bge.c,v
retrieving revision 1.192
diff -u -p -r1.192 if_bge.c
--- if_bge.c	25 Oct 2006 02:37:50 -0000	1.192
+++ if_bge.c	25 Oct 2006 20:25:47 -0000
@@ -2683,7 +2683,7 @@ int
 bge_encap(struct bge_softc *sc, struct mbuf *m_head, u_int32_t *txidx)
 {
 	struct bge_tx_bd	*f = NULL;
-	u_int32_t		frag, cur, cnt = 0;
+	u_int32_t		frag, cur;
 	u_int16_t		csum_flags = 0;
 	struct txdmamap_pool_entry *dma;
 	bus_dmamap_t dmamap;
@@ -2737,6 +2737,12 @@ doit:
 	    BUS_DMA_NOWAIT))
 		return (ENOBUFS);
 
+	/* Sanity check: avoid coming within 16 descriptors
+	 * of the end of the ring.
+	 */
+	if (dmamap->dm_nsegs > (BGE_TX_RING_CNT - sc->bge_txcnt - 16))
+		goto fail_unload;
+
 	for (i = 0; i < dmamap->dm_nsegs; i++) {
 		f = &sc->bge_rdata->bge_tx_ring[frag];
 		if (sc->bge_cdata.bge_tx_chain[frag] != NULL)
@@ -2752,35 +2758,32 @@ doit:
 			f->bge_vlan_tag = 0;
 		}
 #endif
-		/*
-		 * Sanity check: avoid coming within 16 descriptors
-		 * of the end of the ring.
-		 */
-		if ((BGE_TX_RING_CNT - (sc->bge_txcnt + cnt)) < 16)
-			return (ENOBUFS);
 		cur = frag;
 		BGE_INC(frag, BGE_TX_RING_CNT);
-		cnt++;
 	}
 
 	if (i < dmamap->dm_nsegs)
-		return (ENOBUFS);
+		goto fail_unload;
 
 	bus_dmamap_sync(sc->bge_dmatag, dmamap, 0, dmamap->dm_mapsize,
 	    BUS_DMASYNC_PREWRITE);
 
 	if (frag == sc->bge_tx_saved_considx)
-		return (ENOBUFS);
+		goto fail_unload;
 
 	sc->bge_rdata->bge_tx_ring[cur].bge_flags |= BGE_TXBDFLAG_END;
 	sc->bge_cdata.bge_tx_chain[cur] = m_head;
 	SLIST_REMOVE_HEAD(&sc->txdma_list, link);
 	sc->txdma[cur] = dma;
-	sc->bge_txcnt += cnt;
+	sc->bge_txcnt += dmamap->dm_nsegs;
 
 	*txidx = frag;
 
 	return (0);
+
+fail_unload:
+	bus_dmamap_unload(sc->bge_dmatag, dmamap);
+	return (ENOBUFS);
 }
 
 /*

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic