Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 22 Jul 2013 05:45:54 +0000 (UTC)
From:      Pyun YongHyeon <yongari@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r253540 - head/sys/dev/bge
Message-ID:  <201307220545.r6M5js9g035020@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: yongari
Date: Mon Jul 22 05:45:54 2013
New Revision: 253540
URL: http://svnweb.freebsd.org/changeset/base/253540

Log:
  5725 family of devices corrupts TSO packets when TSO DMA buffers
  cross into regions which are within MSS bytes of a 4GB boundary.
  If we encounter the condition, drop the packet.
  
  Reviewed by:	Geans Pin geanspin@Broacom

Modified:
  head/sys/dev/bge/if_bge.c

Modified: head/sys/dev/bge/if_bge.c
==============================================================================
--- head/sys/dev/bge/if_bge.c	Mon Jul 22 03:55:15 2013	(r253539)
+++ head/sys/dev/bge/if_bge.c	Mon Jul 22 05:45:54 2013	(r253540)
@@ -5257,17 +5257,51 @@ bge_encap(struct bge_softc *sc, struct m
 		csum_flags |= BGE_TXBDFLAG_VLAN_TAG;
 		vlan_tag = m->m_pkthdr.ether_vtag;
 	}
-	for (i = 0; ; i++) {
-		d = &sc->bge_ldata.bge_tx_ring[idx];
-		d->bge_addr.bge_addr_lo = BGE_ADDR_LO(segs[i].ds_addr);
-		d->bge_addr.bge_addr_hi = BGE_ADDR_HI(segs[i].ds_addr);
-		d->bge_len = segs[i].ds_len;
-		d->bge_flags = csum_flags;
-		d->bge_vlan_tag = vlan_tag;
-		d->bge_mss = mss;
-		if (i == nsegs - 1)
-			break;
-		BGE_INC(idx, BGE_TX_RING_CNT);
+
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5762 &&
+	    (m->m_pkthdr.csum_flags & CSUM_TSO) != 0) {
+		/*
+		 * 5725 family of devices corrupts TSO packets when TSO DMA
+		 * buffers cross into regions which are within MSS bytes of
+		 * a 4GB boundary.  If we encounter the condition, drop the
+		 * packet.
+		 */
+		for (i = 0; ; i++) {
+			d = &sc->bge_ldata.bge_tx_ring[idx];
+			d->bge_addr.bge_addr_lo = BGE_ADDR_LO(segs[i].ds_addr);
+			d->bge_addr.bge_addr_hi = BGE_ADDR_HI(segs[i].ds_addr);
+			d->bge_len = segs[i].ds_len;
+			if (d->bge_addr.bge_addr_lo + segs[i].ds_len + mss <
+			    d->bge_addr.bge_addr_lo)
+				break;
+			d->bge_flags = csum_flags;
+			d->bge_vlan_tag = vlan_tag;
+			d->bge_mss = mss;
+			if (i == nsegs - 1)
+				break;
+			BGE_INC(idx, BGE_TX_RING_CNT);
+		}
+		if (i != nsegs - 1) {
+			bus_dmamap_sync(sc->bge_cdata.bge_tx_mtag, map,
+			    BUS_DMASYNC_POSTWRITE);
+			bus_dmamap_unload(sc->bge_cdata.bge_tx_mtag, map);
+			m_freem(*m_head);
+			*m_head = NULL;
+			return (EIO);
+		}
+	} else {
+		for (i = 0; ; i++) {
+			d = &sc->bge_ldata.bge_tx_ring[idx];
+			d->bge_addr.bge_addr_lo = BGE_ADDR_LO(segs[i].ds_addr);
+			d->bge_addr.bge_addr_hi = BGE_ADDR_HI(segs[i].ds_addr);
+			d->bge_len = segs[i].ds_len;
+			d->bge_flags = csum_flags;
+			d->bge_vlan_tag = vlan_tag;
+			d->bge_mss = mss;
+			if (i == nsegs - 1)
+				break;
+			BGE_INC(idx, BGE_TX_RING_CNT);
+		}
 	}
 
 	/* Mark the last segment as end of packet... */



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