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);

Reply via email to