summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorbenno <benno@FreeBSD.org>2008-06-12 00:38:54 +0000
committerbenno <benno@FreeBSD.org>2008-06-12 00:38:54 +0000
commit9a4fb697d8ab703202c45908ed0b642a595c6c91 (patch)
tree89207568434b7aba04616ea8ca64e1ef279cb4ca /sys/dev
parent4052a56040128a00c4546c64e0ff4668bf379b83 (diff)
downloadFreeBSD-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')
-rw-r--r--sys/dev/smc/if_smc.c43
-rw-r--r--sys/dev/smc/if_smcvar.h1
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;
OpenPOWER on IntegriCloud