svn commit: r214715 - stable/7/sys/dev/bge

Pyun YongHyeon yongari at FreeBSD.org
Wed Nov 3 00:13:22 UTC 2010


Author: yongari
Date: Wed Nov  3 00:13:22 2010
New Revision: 214715
URL: http://svn.freebsd.org/changeset/base/214715

Log:
  MFC r214087,214219,214251,214292:
  r214087:
    Add workaround for BCM5906 controller silicon bug. If device
    receive two back-to-back send BDs with less than or equal to 8
    total bytes then the device may hang. The two back-to-back send
    BDs must be in the same frame for this failure to occur.
    Thanks to davidch for detailed errata information.
  
    Reviewed by:	davidch
  
  r214219:
    Add workaround for BCM5906 A1 controller silicon bug. When
    auto-negotiation results in half-duplex operation, excess collision
    on the ethernet link may cause internal chip delays that may result
    in subsequent valid frames being dropped due to insufficient
    receive buffer resources. The workaround is to choose de-pipeline
    method as a flow control decision for SDI. De-pipeline method
    allows only 1 data in TxMbuf at a time such that a request to RDMA
    from SDI is made only when TxMbuf is empty. Thanks for david for
    providing detailed errata information.
  
  r214251:
    Apply the same workaround for SDI flow control used on BCM5906 A1
    to BCM6906 A0/A2. This should fix a long standing BCM5906 A2 lockup
    issues. Data sheet explicitly mentions BCM5906 A0, A1 and A2 use
    de-pipelined mode on these revisions.
    Special thanks to Buganini who tried all combinations of
    experimental patches for more than 10 days.
  
    Tested by:	Buganini <buganini <> gmail dot com >
  
  r214292:
    Use bge_chipid to compare controller ids. r214251 incorrectly used
    bge_chiprev.
  
    Reported by:	Buganini <buganini <> gmail dot com >

Modified:
  stable/7/sys/dev/bge/if_bge.c
  stable/7/sys/dev/bge/if_bgereg.h
Directory Properties:
  stable/7/sys/   (props changed)
  stable/7/sys/cddl/contrib/opensolaris/   (props changed)
  stable/7/sys/contrib/dev/acpica/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)

Modified: stable/7/sys/dev/bge/if_bge.c
==============================================================================
--- stable/7/sys/dev/bge/if_bge.c	Wed Nov  3 00:03:26 2010	(r214714)
+++ stable/7/sys/dev/bge/if_bge.c	Wed Nov  3 00:13:22 2010	(r214715)
@@ -374,6 +374,7 @@ static void bge_tick(void *);
 static void bge_stats_clear_regs(struct bge_softc *);
 static void bge_stats_update(struct bge_softc *);
 static void bge_stats_update_regs(struct bge_softc *);
+static struct mbuf *bge_check_short_dma(struct mbuf *);
 static struct mbuf *bge_setup_tso(struct bge_softc *, struct mbuf *,
     uint16_t *);
 static int bge_encap(struct bge_softc *, struct mbuf **, uint32_t *);
@@ -1696,6 +1697,14 @@ bge_blockinit(struct bge_softc *sc)
 		bge_writembx(sc, BGE_MBX_RX_MINI_PROD_LO, 0);
 	}
 
+	/* Choose de-pipeline mode for BCM5906 A0, A1 and A2. */
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5906) {
+		if (sc->bge_chipid == BGE_CHIPID_BCM5906_A0 ||
+		    sc->bge_chipid == BGE_CHIPID_BCM5906_A1 ||
+		    sc->bge_chipid == BGE_CHIPID_BCM5906_A2)
+			CSR_WRITE_4(sc, BGE_ISO_PKT_TX,
+			    (CSR_READ_4(sc, BGE_ISO_PKT_TX) & ~3) | 2);
+	}
 	/*
 	 * The BD ring replenish thresholds control how often the
 	 * hardware fetches new BD's from the producer rings in host
@@ -2632,12 +2641,14 @@ bge_attach(device_t dev)
 	case BGE_ASICREV_BCM5780:
 	case BGE_ASICREV_BCM5714:
 		sc->bge_flags |= BGE_FLAG_5714_FAMILY /* | BGE_FLAG_JUMBO */;
-		/* FALLTHRU */
+		/* FALLTHROUGH */
 	case BGE_ASICREV_BCM5750:
 	case BGE_ASICREV_BCM5752:
 	case BGE_ASICREV_BCM5906:
 		sc->bge_flags |= BGE_FLAG_575X_PLUS;
-		/* FALLTHRU */
+		if (sc->bge_asicrev == BGE_ASICREV_BCM5906)
+			sc->bge_flags |= BGE_FLAG_SHORT_DMA_BUG;
+		/* FALLTHROUGH */
 	case BGE_ASICREV_BCM5705:
 		sc->bge_flags |= BGE_FLAG_5705_PLUS;
 		break;
@@ -4060,6 +4071,39 @@ bge_cksum_pad(struct mbuf *m)
 }
 
 static struct mbuf *
+bge_check_short_dma(struct mbuf *m)
+{
+	struct mbuf *n;
+	int found;
+
+	/*
+	 * If device receive two back-to-back send BDs with less than
+	 * or equal to 8 total bytes then the device may hang.  The two
+	 * back-to-back send BDs must in the same frame for this failure
+	 * to occur.  Scan mbuf chains and see whether two back-to-back
+	 * send BDs are there. If this is the case, allocate new mbuf
+	 * and copy the frame to workaround the silicon bug.
+	 */
+	for (n = m, found = 0; n != NULL; n = n->m_next) {
+		if (n->m_len < 8) {
+			found++;
+			if (found > 1)
+				break;
+			continue;
+		}
+		found = 0;
+	}
+
+	if (found > 1) {
+		n = m_defrag(m, M_DONTWAIT);
+		if (n == NULL)
+			m_freem(m);
+	} else
+		n = m;
+	return (n);
+}
+
+static struct mbuf *
 bge_setup_tso(struct bge_softc *sc, struct mbuf *m, uint16_t *mss)
 {
 	struct ip *ip;
@@ -4132,6 +4176,13 @@ bge_encap(struct bge_softc *sc, struct m
 	csum_flags = 0;
 	mss = 0;
 	vlan_tag = 0;
+	if ((sc->bge_flags & BGE_FLAG_SHORT_DMA_BUG) != 0 &&
+	    m->m_next != NULL) {
+		*m_head = bge_check_short_dma(m);
+		if (*m_head == NULL)
+			return (ENOBUFS);
+		m = *m_head;
+	}
 	if ((m->m_pkthdr.csum_flags & CSUM_TSO) != 0) {
 		*m_head = m = bge_setup_tso(sc, m, &mss);
 		if (*m_head == NULL)

Modified: stable/7/sys/dev/bge/if_bgereg.h
==============================================================================
--- stable/7/sys/dev/bge/if_bgereg.h	Wed Nov  3 00:03:26 2010	(r214714)
+++ stable/7/sys/dev/bge/if_bgereg.h	Wed Nov  3 00:13:22 2010	(r214715)
@@ -306,6 +306,7 @@
 #define	BGE_CHIPID_BCM5787_A0		0xb000
 #define	BGE_CHIPID_BCM5787_A1		0xb001
 #define	BGE_CHIPID_BCM5787_A2		0xb002
+#define	BGE_CHIPID_BCM5906_A0		0xc000
 #define	BGE_CHIPID_BCM5906_A1		0xc001
 #define	BGE_CHIPID_BCM5906_A2		0xc002
 #define	BGE_CHIPID_BCM57780_A0		0x57780000
@@ -880,6 +881,7 @@
 #define	BGE_SDI_STATS_CTL		0x0C08
 #define	BGE_SDI_STATS_ENABLE_MASK	0x0C0C
 #define	BGE_SDI_STATS_INCREMENT_MASK	0x0C10
+#define	BGE_ISO_PKT_TX			0x0C20
 #define	BGE_LOCSTATS_COS0		0x0C80
 #define	BGE_LOCSTATS_COS1		0x0C84
 #define	BGE_LOCSTATS_COS2		0x0C88
@@ -2728,6 +2730,7 @@ struct bge_softc {
 #define	BGE_FLAG_40BIT_BUG	0x01000000
 #define	BGE_FLAG_4G_BNDRY_BUG	0x02000000
 #define	BGE_FLAG_RX_ALIGNBUG	0x04000000
+#define	BGE_FLAG_SHORT_DMA_BUG	0x08000000
 	uint32_t		bge_phy_flags;
 #define	BGE_PHY_WIRESPEED	0x00000001
 #define	BGE_PHY_ADC_BUG		0x00000002


More information about the svn-src-stable-7 mailing list