summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarius <marius@FreeBSD.org>2011-03-26 22:39:23 +0000
committermarius <marius@FreeBSD.org>2011-03-26 22:39:23 +0000
commitcd4121bde0c1110bf1f3ca8e8e8aba116f005416 (patch)
treee30217938c41e6ac1acbcb0b64f8448650997de5
parent59f8f1111b705469135b2c909b1ff58bd73c8142 (diff)
downloadFreeBSD-src-cd4121bde0c1110bf1f3ca8e8e8aba116f005416.zip
FreeBSD-src-cd4121bde0c1110bf1f3ca8e8e8aba116f005416.tar.gz
Wait until the DMA engine is stopped before unmapping buffers and
descriptors, which fixes DMA errors seen on sparc64. Obtained from: OpenBSD MFC after: 1 week
-rw-r--r--sys/dev/dc/if_dc.c26
1 files changed, 25 insertions, 1 deletions
diff --git a/sys/dev/dc/if_dc.c b/sys/dev/dc/if_dc.c
index bfc4401..6d0ebc0 100644
--- a/sys/dev/dc/if_dc.c
+++ b/sys/dev/dc/if_dc.c
@@ -3917,7 +3917,7 @@ dc_stop(struct dc_softc *sc)
struct dc_list_data *ld;
struct dc_chain_data *cd;
int i;
- uint32_t ctl;
+ uint32_t ctl, isr;
DC_LOCK_ASSERT(sc);
@@ -3932,6 +3932,30 @@ dc_stop(struct dc_softc *sc)
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__);
+ }
+
CSR_WRITE_4(sc, DC_IMR, 0x00000000);
CSR_WRITE_4(sc, DC_TXADDR, 0x00000000);
CSR_WRITE_4(sc, DC_RXADDR, 0x00000000);
OpenPOWER on IntegriCloud