svn commit: r219407 - head/sys/dev/dc

Pyun YongHyeon yongari at FreeBSD.org
Tue Mar 8 19:49:16 UTC 2011


Author: yongari
Date: Tue Mar  8 19:49:16 2011
New Revision: 219407
URL: http://svn.freebsd.org/changeset/base/219407

Log:
  Rearrange dc_tx_underrun() a bit to correctly set TX FIFO threshold
  value. Controllers that always require "store and forward" mode(
  Davicom and PNIC 82C168) have no way to recover from TX underrun
  except completely reinitializing hardware. Previously only Davicom
  was reinitialized and the TX FIFO threshold was changed not to use
  "store and forward" mode after reinitialization since the default
  FIFO threshold value was 0. This effectively disabled Davicom
  controller's "store and forward" mode once it encountered TX
  underruns. In theory, this can cause watchodg timeouts.
  
  Intel 21143 controller requires TX MAC should be idle before
  changing TX FIFO threshold. So driver tried to disable TX MAC and
  checked whether it saw the idle state of TX MAC. Driver should
  perform full hardware reinitialization on failing to enter to idle
  state and it should not touch TX MAC again once it performed full
  reinitialization.
  
  While I'm here remove resetting TX FIFO threshold to 0 when
  interface is put into down state. If driver ever encountered TX
  underrun, it's likely to trigger TX underrun again whenever
  interface is brought to up again. Keeping old/learned TX FIFO
  threshold value shall reduce the chance of seeing TX underrns in
  next run.

Modified:
  head/sys/dev/dc/if_dc.c

Modified: head/sys/dev/dc/if_dc.c
==============================================================================
--- head/sys/dev/dc/if_dc.c	Tue Mar  8 19:05:14 2011	(r219406)
+++ head/sys/dev/dc/if_dc.c	Tue Mar  8 19:49:16 2011	(r219407)
@@ -3142,50 +3142,57 @@ dc_tick(void *xsc)
 static void
 dc_tx_underrun(struct dc_softc *sc)
 {
-	uint32_t isr;
-	int i;
+	uint32_t netcfg, isr;
+	int i, reinit;
 
-	if (DC_IS_DAVICOM(sc)) {
-		sc->dc_ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
-		dc_init_locked(sc);
-	}
-
-	if (DC_IS_INTEL(sc)) {
-		/*
-		 * The real 21143 requires that the transmitter be idle
-		 * in order to change the transmit threshold or store
-		 * and forward state.
-		 */
-		DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON);
-
-		for (i = 0; i < DC_TIMEOUT; i++) {
-			isr = CSR_READ_4(sc, DC_ISR);
-			if (isr & DC_ISR_TX_IDLE)
-				break;
-			DELAY(10);
-		}
-		if (i == DC_TIMEOUT) {
-			device_printf(sc->dc_dev,
-			    "%s: failed to force tx to idle state\n",
-			    __func__);
-			sc->dc_ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
-			dc_init_locked(sc);
+	reinit = 0;
+	netcfg = CSR_READ_4(sc, DC_NETCFG);
+	device_printf(sc->dc_dev, "TX underrun -- ");
+	if ((sc->dc_flags & DC_TX_STORENFWD) == 0) {
+		if (sc->dc_txthresh + DC_TXTHRESH_INC > DC_TXTHRESH_MAX) {
+			printf("using store and forward mode\n");
+			netcfg |= DC_NETCFG_STORENFWD;
+		} else {
+			printf("increasing TX threshold\n");
+			sc->dc_txthresh += DC_TXTHRESH_INC;
+			netcfg &= ~DC_NETCFG_TX_THRESH;
+			netcfg |= sc->dc_txthresh;
+		}
+
+		if (DC_IS_INTEL(sc)) {
+			/*
+			 * The real 21143 requires that the transmitter be idle
+			 * in order to change the transmit threshold or store
+			 * and forward state.
+			 */
+			CSR_WRITE_4(sc, DC_NETCFG, netcfg & ~DC_NETCFG_TX_ON);
+
+			for (i = 0; i < DC_TIMEOUT; i++) {
+				isr = CSR_READ_4(sc, DC_ISR);
+				if (isr & DC_ISR_TX_IDLE)
+					break;
+				DELAY(10);
+			}
+			if (i == DC_TIMEOUT) {
+				device_printf(sc->dc_dev,
+				    "%s: failed to force tx to idle state\n",
+				    __func__);
+				reinit++;
+			}
 		}
+	} else {
+		printf("resetting\n");
+		reinit++;
 	}
 
-	device_printf(sc->dc_dev, "TX underrun -- ");
-	sc->dc_txthresh += DC_TXTHRESH_INC;
-	if (sc->dc_txthresh > DC_TXTHRESH_MAX) {
-		printf("using store and forward mode\n");
-		DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD);
+	if (reinit == 0) {
+		CSR_WRITE_4(sc, DC_NETCFG, netcfg);
+		if (DC_IS_INTEL(sc))
+			CSR_WRITE_4(sc, DC_NETCFG, netcfg | DC_NETCFG_TX_ON);
 	} else {
-		printf("increasing TX threshold\n");
-		DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_TX_THRESH);
-		DC_SETBIT(sc, DC_NETCFG, sc->dc_txthresh);
+		sc->dc_ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+		dc_init_locked(sc);
 	}
-
-	if (DC_IS_INTEL(sc))
-		DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON);
 }
 
 #ifdef DEVICE_POLLING
@@ -3825,7 +3832,6 @@ dc_ioctl(struct ifnet *ifp, u_long comma
 				if (need_setfilt)
 					dc_setfilt(sc);
 			} else {
-				sc->dc_txthresh = 0;
 				ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
 				dc_init_locked(sc);
 			}


More information about the svn-src-all mailing list