svn commit: r220106 - head/sys/dev/dc
Pyun YongHyeon
yongari at FreeBSD.org
Mon Mar 28 19:08:53 UTC 2011
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.
More information about the svn-src-head
mailing list