diff --git a/sys/dev/netif/my/if_my.c b/sys/dev/netif/my/if_my.c index 1111111..2222222 100644 --- a/sys/dev/netif/my/if_my.c +++ b/sys/dev/netif/my/if_my.c @@ -1646,9 +1646,19 @@ my_stop(struct my_softc * sc) ifp->if_timer = 0; + /* + * Put the transmit and receive logic in the idle state and wait + * for the engines to actually stop before freeing the buffers, + * otherwise an in-flight DMA can write into freed mbuf clusters. + */ MY_CLRBIT(sc, MY_TCRRCR, (MY_RE | MY_TE)); + for (i = 0; i < MY_TIMEOUT; i++) { + DELAY(10); + if (!(CSR_READ_4(sc, MY_TCRRCR) & (MY_TXRUN | MY_RXRUN))) + break; + } + if (i == MY_TIMEOUT) + kprintf("my%d: failed to force tx and rx to idle\n", + sc->my_unit); CSR_WRITE_4(sc, MY_IMR, 0x00000000); CSR_WRITE_4(sc, MY_TXLBA, 0x00000000); CSR_WRITE_4(sc, MY_RXLBA, 0x00000000);