diff options
-rw-r--r-- | sys/dev/fdc/fdc.c | 24 | ||||
-rw-r--r-- | sys/dev/fdc/fdcvar.h | 2 |
2 files changed, 23 insertions, 3 deletions
diff --git a/sys/dev/fdc/fdc.c b/sys/dev/fdc/fdc.c index 139285c..6df202c 100644 --- a/sys/dev/fdc/fdc.c +++ b/sys/dev/fdc/fdc.c @@ -761,8 +761,17 @@ fdc_worker(struct fdc_data *fdc) if (fdc->bp == NULL) msleep(&fdc->head, &fdc->fdc_mtx, PRIBIO, "-", hz); - } while (fdc->bp == NULL); + } while (fdc->bp == NULL && + (fdc->flags & FDC_KTHREAD_EXIT) == 0); mtx_unlock(&fdc->fdc_mtx); + + if (fdc->bp == NULL) + /* + * Nothing to do, worker thread has been + * requested to stop. + */ + return (0); + bp = fdc->bp; fd = fdc->fd = bp->bio_driver1; fdc->retry = 0; @@ -1118,7 +1127,8 @@ fdc_thread(void *arg) fdc = arg; int i; - for (;;) { + fdc->flags |= FDC_KTHREAD_ALIVE; + while ((fdc->flags & FDC_KTHREAD_EXIT) == 0) { i = fdc_worker(fdc); if (i && debugflags & 0x20) { if (fdc->bp != NULL) { @@ -1129,6 +1139,8 @@ fdc_thread(void *arg) } fdc->retry += i; } + fdc->flags &= ~(FDC_KTHREAD_EXIT | FDC_KTHREAD_ALIVE); + wakeup(&fdc->fdc_thread); } /* @@ -1624,7 +1636,13 @@ fdc_detach(device_t dev) if ((error = bus_generic_detach(dev))) return (error); - /* XXX: kill thread */ + /* kill worker thread */ + fdc->flags |= FDC_KTHREAD_EXIT; + mtx_lock(&fdc->fdc_mtx); + while ((fdc->flags & FDC_KTHREAD_ALIVE) != 0) + msleep(&fdc->fdc_thread, &fdc->fdc_mtx, PRIBIO, "fdcdet", 0); + mtx_unlock(&fdc->fdc_mtx); + /* reset controller, turn motor off */ fdout_wr(fdc, 0); diff --git a/sys/dev/fdc/fdcvar.h b/sys/dev/fdc/fdcvar.h index 5ecf912..acba77e 100644 --- a/sys/dev/fdc/fdcvar.h +++ b/sys/dev/fdc/fdcvar.h @@ -46,6 +46,8 @@ struct fdc_data { #define FDC_HAS_FIFO 0x10 #define FDC_NEEDS_RESET 0x20 #define FDC_NODMA 0x40 +#define FDC_KTHREAD_EXIT 0x1000 /* request worker thread to stop */ +#define FDC_KTHREAD_ALIVE 0x2000 /* worker thread is alive */ struct fd_data *fd; /* The active drive */ int retry; int fdout; /* mirror of the w/o digital output reg */ |