Daniel,
Can you try this diff? It won't get rid of the watchdog timeout, but
hopefully it will prevent the DMA error.
Index: dc.c
===================================================================
RCS file: /cvs/src/sys/dev/ic/dc.c,v
retrieving revision 1.116
diff -u -p -r1.116 dc.c
--- dc.c 5 Aug 2010 07:57:04 -0000 1.116
+++ dc.c 3 Mar 2011 20:22:12 -0000
@@ -3059,6 +3059,7 @@ void
dc_stop(struct dc_softc *sc, int softonly)
{
struct ifnet *ifp;
+ u_int32_t isr;
int i;
ifp = &sc->sc_arpcom.ac_if;
@@ -3070,6 +3071,28 @@ dc_stop(struct dc_softc *sc, int softonl
if (!softonly) {
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))
+ printf("%s: failed to force tx to idle state\n",
+ sc->sc_dev.dv_xname);
+ if (!((isr & DC_ISR_RX_STATE) == DC_RXSTATE_STOPPED) &&
+ !DC_HAS_BROKEN_RXSTATE(sc))
+ printf("%s: failed to force rx to idle state\n",
+ sc->sc_dev.dv_xname);
+ }
+
CSR_WRITE_4(sc, DC_IMR, 0x00000000);
CSR_WRITE_4(sc, DC_TXADDR, 0x00000000);
CSR_WRITE_4(sc, DC_RXADDR, 0x00000000);