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
This commit is contained in:
parent
c45e1b3cad
commit
1da7683a7c
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=220106
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user