Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 17 Jul 2013 04:53:53 +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: r253408 - head/sys/dev/bge
Message-ID:  <201307170453.r6H4rrHe038894@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: yongari
Date: Wed Jul 17 04:53:53 2013
New Revision: 253408
URL: http://svnweb.freebsd.org/changeset/base/253408

Log:
  Implement workaround for BCM5719/BCM5720 TX hang.
  The read DMA request logic operation is based on having sufficient
  available space in the transmit data buffer (TXMBUF) before a read
  DMA can be requested.  There are four read DMA channels that use
  the TXMBUF, and the logic checks if the available free space in the
  TXMBUF is large enough for all the data in the four Send Buffers
  for which buffer descriptors have been fetched.  The Enable_Request
  signal is asserted only if the free TXMBUF space is larger than the
  sum of the four DMA length registers.  The power-up default value
  of BGE_RDMA_LSO_CRPTEN_CTRL register bit 25 (bit 21 on BCM5720) is
  zero, which selects the DMA length registers to connect to the
  input of the adder block.  The DMA length registers are
  asynchronously reset following BCM5719/BCM5720 power-up, and due to
  the lack of synchronous deassertion of the length registers reset
  signal these resisters may contain uninitialized values following
  the reset deassertion.
  In the case of the failure the uninitialized DMA length register
  values added up to more than the TXMBUF size, which prevented the
  assertion of the Enable_Request signal and any subsequent read DMA
  to start.  This lockup condition is the root cause of failing to
  generate any transmit traffic.
  
  To workaround the issue, select alternate output of multiplexers
  and transmit the first four Ethernet frames. This overwrites the
  DMA length registers with valid values.
  
  Reported by:	Geans Pin <geanspin@broadcom.com>
  Reviewed by:	Geans Pin <geanspin@broadcom.com>

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

Modified: head/sys/dev/bge/if_bge.c
==============================================================================
--- head/sys/dev/bge/if_bge.c	Wed Jul 17 02:37:40 2013	(r253407)
+++ head/sys/dev/bge/if_bge.c	Wed Jul 17 04:53:53 2013	(r253408)
@@ -2508,6 +2508,24 @@ bge_blockinit(struct bge_softc *sc)
 	CSR_WRITE_4(sc, BGE_RDMA_MODE, val);
 	DELAY(40);
 
+	if (sc->bge_flags & BGE_FLAG_RDMA_BUG) {
+		for (i = 0; i < BGE_NUM_RDMA_CHANNELS / 2; i++) {
+			val = CSR_READ_4(sc, BGE_RDMA_LENGTH + i * 4);
+			if ((val & 0xFFFF) > BGE_FRAMELEN)
+				break;
+			if (((val >> 16) & 0xFFFF) > BGE_FRAMELEN)
+				break;
+		}
+		if (i != BGE_NUM_RDMA_CHANNELS / 2) {
+			val = CSR_READ_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL);
+			if (sc->bge_asicrev == BGE_ASICREV_BCM5719)
+				val |= BGE_RDMA_TX_LENGTH_WA_5719;
+			else
+				val |= BGE_RDMA_TX_LENGTH_WA_5720;
+			CSR_WRITE_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL, val);
+		}
+	}
+
 	/* Turn on RX data completion state machine */
 	CSR_WRITE_4(sc, BGE_RDC_MODE, BGE_RDCMODE_ENABLE);
 
@@ -3319,10 +3337,18 @@ bge_attach(device_t dev)
 		sc->bge_flags |= BGE_FLAG_5717_PLUS | BGE_FLAG_5755_PLUS |
 		    BGE_FLAG_575X_PLUS | BGE_FLAG_5705_PLUS | BGE_FLAG_JUMBO |
 		    BGE_FLAG_JUMBO_FRAME;
-		if (sc->bge_asicrev == BGE_ASICREV_BCM5719 &&
-		    sc->bge_chipid == BGE_CHIPID_BCM5719_A0) {
-			/* Jumbo frame on BCM5719 A0 does not work. */
-			sc->bge_flags &= ~BGE_FLAG_JUMBO;
+		if (sc->bge_asicrev == BGE_ASICREV_BCM5719 ||
+		    sc->bge_asicrev == BGE_ASICREV_BCM5720) {
+			/*
+			 * Enable work around for DMA engine miscalculation
+			 * of TXMBUF available space.
+			 */
+			sc->bge_flags |= BGE_FLAG_RDMA_BUG;
+			if (sc->bge_asicrev == BGE_ASICREV_BCM5719 &&
+			    sc->bge_chipid == BGE_CHIPID_BCM5719_A0) {
+				/* Jumbo frame on BCM5719 A0 does not work. */
+				sc->bge_flags &= ~BGE_FLAG_JUMBO;
+			}
 		}
 		break;
 	case BGE_ASICREV_BCM5755:
@@ -4740,6 +4766,7 @@ bge_stats_update_regs(struct bge_softc *
 {
 	struct ifnet *ifp;
 	struct bge_mac_stats *stats;
+	uint32_t val;
 
 	ifp = sc->bge_ifp;
 	stats = &sc->bge_mac_stats;
@@ -4840,6 +4867,24 @@ bge_stats_update_regs(struct bge_softc *
 	ifp->if_collisions = (u_long)stats->etherStatsCollisions;
 	ifp->if_ierrors = (u_long)(stats->NoMoreRxBDs + stats->InputDiscards +
 	    stats->InputErrors);
+
+	if (sc->bge_flags & BGE_FLAG_RDMA_BUG) {
+		/*
+		 * If controller transmitted more than BGE_NUM_RDMA_CHANNELS
+		 * frames, it's safe to disable workaround for DMA engine's
+		 * miscalculation of TXMBUF space.
+		 */
+		if (stats->ifHCOutUcastPkts + stats->ifHCOutMulticastPkts +
+		    stats->ifHCOutBroadcastPkts > BGE_NUM_RDMA_CHANNELS) {
+			val = CSR_READ_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL);
+			if (sc->bge_asicrev == BGE_ASICREV_BCM5719)
+				val &= ~BGE_RDMA_TX_LENGTH_WA_5719;
+			else
+				val &= ~BGE_RDMA_TX_LENGTH_WA_5720;
+			CSR_WRITE_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL, val);
+			sc->bge_flags &= ~BGE_FLAG_RDMA_BUG;
+		}
+	}
 }
 
 static void

Modified: head/sys/dev/bge/if_bgereg.h
==============================================================================
--- head/sys/dev/bge/if_bgereg.h	Wed Jul 17 02:37:40 2013	(r253407)
+++ head/sys/dev/bge/if_bgereg.h	Wed Jul 17 04:53:53 2013	(r253408)
@@ -1586,6 +1586,8 @@
 #define	BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_BD_512	0x00020000
 #define	BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_BD_4K	0x00030000
 #define	BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_LSO_4K	0x000C0000
+#define	BGE_RDMA_TX_LENGTH_WA_5719		0x02000000
+#define	BGE_RDMA_TX_LENGTH_WA_5720		0x00200000
 
 /* BD Read DMA Mode register */
 #define	BGE_RDMA_BD_MODE		0x4A00
@@ -1603,6 +1605,9 @@
 #define	BGE_RDMA_NON_LSO_MODE_RESET	0x00000001
 #define	BGE_RDMA_NON_LSO_MODE_ENABLE	0x00000002
 
+#define	BGE_RDMA_LENGTH			0x4BE0
+#define	BGE_NUM_RDMA_CHANNELS		4
+
 /*
  * Write DMA control registers
  */
@@ -2972,6 +2977,7 @@ struct bge_softc {
 #define	BGE_FLAG_SHORT_DMA_BUG	0x08000000
 #define	BGE_FLAG_4K_RDMA_BUG	0x10000000
 #define	BGE_FLAG_MBOX_REORDER	0x20000000
+#define	BGE_FLAG_RDMA_BUG	0x40000000
 	uint32_t		bge_mfw_flags;	/* Management F/W flags */
 #define	BGE_MFW_ON_RXCPU	0x00000001
 #define	BGE_MFW_ON_APE		0x00000002



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