Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 28 Mar 2011 19:08: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: r220106 - head/sys/dev/dc
Message-ID:  <201103281908.p2SJ8rdR003681@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: yongari
Date: Mon Mar 28 19:08:53 2011
New Revision: 220106
URL: http://svn.freebsd.org/changeset/base/220106

Log:
  Revise r220046 by introducing dc_netcfg_wait() which waits the end
  of active DMA cycle. dc_setcfg() also has to wait until the DMA
  engine is stopped so using a common function to handle the job is
  better than duplicating the code.
  
  No objection from:	marius

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

Modified: head/sys/dev/dc/if_dc.c
==============================================================================
--- head/sys/dev/dc/if_dc.c	Mon Mar 28 19:03:56 2011	(r220105)
+++ head/sys/dev/dc/if_dc.c	Mon Mar 28 19:08:53 2011	(r220106)
@@ -279,6 +279,7 @@ static void dc_miibus_statchg(device_t);
 static void dc_miibus_mediainit(device_t);
 
 static void dc_setcfg(struct dc_softc *, int);
+static void dc_netcfg_wait(struct dc_softc *);
 static uint32_t dc_mchash_le(struct dc_softc *, const uint8_t *);
 static uint32_t dc_mchash_be(const uint8_t *);
 static void dc_setfilt_21143(struct dc_softc *);
@@ -1370,6 +1371,32 @@ dc_setfilt(struct dc_softc *sc)
 		dc_setfilt_xircom(sc);
 }
 
+static void
+dc_netcfg_wait(struct dc_softc *sc)
+{
+	uint32_t isr;
+	int i;
+
+	for (i = 0; i < DC_TIMEOUT; i++) {
+		isr = CSR_READ_4(sc, DC_ISR);
+		if (isr & DC_ISR_TX_IDLE &&
+		    ((isr & DC_ISR_RX_STATE) == DC_RXSTATE_STOPPED ||
+		    (isr & DC_ISR_RX_STATE) == DC_RXSTATE_WAIT))
+			break;
+		DELAY(10);
+	}
+	if (i == DC_TIMEOUT) {
+		if (!(isr & DC_ISR_TX_IDLE) && !DC_IS_ASIX(sc))
+			device_printf(sc->dc_dev,
+			    "%s: failed to force tx to idle state\n", __func__);
+		if (!((isr & DC_ISR_RX_STATE) == DC_RXSTATE_STOPPED ||
+		    (isr & DC_ISR_RX_STATE) == DC_RXSTATE_WAIT) &&
+		    !DC_HAS_BROKEN_RXSTATE(sc))
+			device_printf(sc->dc_dev,
+			    "%s: failed to force rx to idle state\n", __func__);
+	}
+}
+
 /*
  * In order to fiddle with the 'full-duplex' and '100Mbps' bits in
  * the netconfig register, we first have to put the transmit and/or
@@ -1378,8 +1405,7 @@ dc_setfilt(struct dc_softc *sc)
 static void
 dc_setcfg(struct dc_softc *sc, int media)
 {
-	int i, restart = 0, watchdogreg;
-	uint32_t isr;
+	int restart = 0, watchdogreg;
 
 	if (IFM_SUBTYPE(media) == IFM_NONE)
 		return;
@@ -1387,28 +1413,7 @@ dc_setcfg(struct dc_softc *sc, int media
 	if (CSR_READ_4(sc, DC_NETCFG) & (DC_NETCFG_TX_ON | DC_NETCFG_RX_ON)) {
 		restart = 1;
 		DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_TX_ON | DC_NETCFG_RX_ON));
-
-		for (i = 0; i < DC_TIMEOUT; i++) {
-			isr = CSR_READ_4(sc, DC_ISR);
-			if (isr & DC_ISR_TX_IDLE &&
-			    ((isr & DC_ISR_RX_STATE) == DC_RXSTATE_STOPPED ||
-			    (isr & DC_ISR_RX_STATE) == DC_RXSTATE_WAIT))
-				break;
-			DELAY(10);
-		}
-
-		if (i == DC_TIMEOUT) {
-			if (!(isr & DC_ISR_TX_IDLE) && !DC_IS_ASIX(sc))
-				device_printf(sc->dc_dev,
-				    "%s: failed to force tx to idle state\n",
-				    __func__);
-			if (!((isr & DC_ISR_RX_STATE) == DC_RXSTATE_STOPPED ||
-			    (isr & DC_ISR_RX_STATE) == DC_RXSTATE_WAIT) &&
-			    !DC_HAS_BROKEN_RXSTATE(sc))
-				device_printf(sc->dc_dev,
-				    "%s: failed to force rx to idle state\n",
-				    __func__);
-		}
+		dc_netcfg_wait(sc);
 	}
 
 	if (IFM_SUBTYPE(media) == IFM_100_TX) {
@@ -3917,7 +3922,7 @@ dc_stop(struct dc_softc *sc)
 	struct dc_list_data *ld;
 	struct dc_chain_data *cd;
 	int i;
-	uint32_t ctl, isr;
+	uint32_t ctl, netcfg;
 
 	DC_LOCK_ASSERT(sc);
 
@@ -3928,38 +3933,21 @@ dc_stop(struct dc_softc *sc)
 	callout_stop(&sc->dc_stat_ch);
 	callout_stop(&sc->dc_wdog_ch);
 	sc->dc_wdog_timer = 0;
+	sc->dc_link = 0;
 
 	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
 
-	DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_RX_ON | DC_NETCFG_TX_ON));
-
-	for (i = 0; i < DC_TIMEOUT; i++) {
-		isr = CSR_READ_4(sc, DC_ISR);
-		if ((isr & DC_ISR_TX_IDLE ||
-		    (isr & DC_ISR_TX_STATE) == DC_TXSTATE_RESET) &&
-		    (isr & DC_ISR_RX_STATE) == DC_RXSTATE_STOPPED)
-			break;
-		DELAY(10);
-	}
-
-	if (i == DC_TIMEOUT) {
-		if (!((isr & DC_ISR_TX_IDLE) ||
-		    (isr & DC_ISR_TX_STATE) == DC_TXSTATE_RESET) &&
-		    !DC_IS_ASIX(sc) && !DC_IS_DAVICOM(sc))
-			device_printf(sc->dc_dev,
-			    "%s: failed to force tx to idle state\n",
-			    __func__);
-		if (!((isr & DC_ISR_RX_STATE) == DC_RXSTATE_STOPPED) &&
-		    !DC_HAS_BROKEN_RXSTATE(sc))
-			device_printf(sc->dc_dev,
-			    "%s: failed to force rx to idle state\n",
-			    __func__);
-	}
-
+	netcfg = CSR_READ_4(sc, DC_NETCFG);
+	if (netcfg & (DC_NETCFG_RX_ON | DC_NETCFG_TX_ON))
+		CSR_WRITE_4(sc, DC_NETCFG,
+		   netcfg & ~(DC_NETCFG_RX_ON | DC_NETCFG_TX_ON));
 	CSR_WRITE_4(sc, DC_IMR, 0x00000000);
+	/* Wait the completion of TX/RX SM. */
+	if (netcfg & (DC_NETCFG_RX_ON | DC_NETCFG_TX_ON))
+		dc_netcfg_wait(sc);
+
 	CSR_WRITE_4(sc, DC_TXADDR, 0x00000000);
 	CSR_WRITE_4(sc, DC_RXADDR, 0x00000000);
-	sc->dc_link = 0;
 
 	/*
 	 * Free data in the RX lists.



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