diff options
author | benno <benno@FreeBSD.org> | 2008-06-12 00:38:54 +0000 |
---|---|---|
committer | benno <benno@FreeBSD.org> | 2008-06-12 00:38:54 +0000 |
commit | 9a4fb697d8ab703202c45908ed0b642a595c6c91 (patch) | |
tree | 89207568434b7aba04616ea8ca64e1ef279cb4ca /sys/dev/smc | |
parent | 4052a56040128a00c4546c64e0ff4668bf379b83 (diff) | |
download | FreeBSD-src-9a4fb697d8ab703202c45908ed0b642a595c6c91.zip FreeBSD-src-9a4fb697d8ab703202c45908ed0b642a595c6c91.tar.gz |
Make sure we drain our taskqueues and stop our callouts in detach.
Diffstat (limited to 'sys/dev/smc')
-rw-r--r-- | sys/dev/smc/if_smc.c | 43 | ||||
-rw-r--r-- | sys/dev/smc/if_smcvar.h | 1 |
2 files changed, 37 insertions, 7 deletions
diff --git a/sys/dev/smc/if_smc.c b/sys/dev/smc/if_smc.c index 966c710..81e468e 100644 --- a/sys/dev/smc/if_smc.c +++ b/sys/dev/smc/if_smc.c @@ -101,6 +101,7 @@ static const char *smc_chip_ids[16] = { static void smc_init(void *); static void smc_start(struct ifnet *); +static void smc_stop(struct smc_softc *); static int smc_ioctl(struct ifnet *, u_long, caddr_t); static void smc_init_locked(struct smc_softc *); @@ -278,6 +279,7 @@ smc_attach(device_t dev) error = 0; sc->smc_dev = dev; + sc->smc_shutdown = 0; /* Set up watchdog callout. */ callout_init(&sc->smc_watchdog, 1); @@ -388,9 +390,19 @@ smc_detach(device_t dev) struct smc_softc *sc; sc = device_get_softc(dev); - - callout_stop(&sc->smc_watchdog); - + SMC_LOCK(sc); + sc->smc_shutdown = 1; + smc_stop(sc); + SMC_UNLOCK(sc); + + if (sc->smc_tq != NULL) { + taskqueue_drain(sc->smc_tq, &sc->smc_intr); + taskqueue_drain(sc->smc_tq, &sc->smc_rx); + taskqueue_drain(sc->smc_tq, &sc->smc_tx); + taskqueue_free(sc->smc_tq); + sc->smc_tq = NULL; + } + #ifdef DEVICE_POLLING if (sc->smc_ifp->if_capenable & IFCAP_POLLING) ether_poll_deregister(sc->smc_ifp); @@ -405,6 +417,7 @@ smc_detach(device_t dev) } if (sc->smc_miibus != NULL) { + callout_stop(&sc->smc_mii_tick_ch); device_delete_child(sc->smc_dev, sc->smc_miibus); bus_generic_detach(sc->smc_dev); } @@ -422,9 +435,6 @@ smc_detach(device_t dev) bus_release_resource(sc->smc_dev, SYS_RES_IRQ, sc->smc_irq_rid, sc->smc_irq); - if (sc->smc_tq != NULL) - taskqueue_free(sc->smc_tq); - if (mtx_initialized(&sc->smc_mtx)) mtx_destroy(&sc->smc_mtx); @@ -530,7 +540,11 @@ smc_task_tx(void *context, int pending) sc = ifp->if_softc; SMC_LOCK(sc); - + if (sc->smc_shutdown == 1) { + SMC_UNLOCK(sc); + return; + } + if (sc->smc_pending == NULL) { SMC_UNLOCK(sc); goto next_packet; @@ -633,6 +647,10 @@ smc_task_rx(void *context, int pending) mhead = mtail = NULL; SMC_LOCK(sc); + if (sc->smc_shutdown == 1) { + SMC_UNLOCK(sc); + return; + } packet = smc_read_1(sc, FIFO_RX); while ((packet & FIFO_EMPTY) == 0) { @@ -774,6 +792,11 @@ smc_task_intr(void *context, int pending) sc = ifp->if_softc; SMC_LOCK(sc); + if (sc->smc_shutdown == 1) { + SMC_UNLOCK(sc); + return; + } + smc_select_bank(sc, 2); /* @@ -1224,6 +1247,12 @@ smc_watchdog(void *arg) struct smc_softc *sc; sc = (struct smc_softc *)arg; + SMC_LOCK(sc); + if (sc->smc_shutdown == 1) { + SMC_UNLOCK(sc); + return; + } + SMC_UNLOCK(sc); device_printf(sc->smc_dev, "watchdog timeout\n"); taskqueue_enqueue_fast(sc->smc_tq, &sc->smc_intr); } diff --git a/sys/dev/smc/if_smcvar.h b/sys/dev/smc/if_smcvar.h index 9bff17d..7463d0a 100644 --- a/sys/dev/smc/if_smcvar.h +++ b/sys/dev/smc/if_smcvar.h @@ -35,6 +35,7 @@ struct smc_softc { u_int smc_chip; u_int smc_rev; u_int smc_mask; + u_int smc_shutdown; /* Resources */ int smc_usemem; |