Index: sys/dev/fdc/fdc.c =================================================================== --- sys/dev/fdc/fdc.c +++ sys/dev/fdc/fdc.c @@ -261,6 +261,7 @@ struct g_provider *fd_provider; device_t dev; struct bio_queue_head fd_bq; + bool gone; }; #define FD_NOT_VALID -2 @@ -1398,6 +1399,7 @@ static g_access_t fd_access; static g_start_t fd_start; static g_ioctl_t fd_ioctl; +static g_provgone_t fd_providergone; struct g_class g_fd_class = { .name = "FD", @@ -1405,6 +1407,7 @@ .start = fd_start, .access = fd_access, .ioctl = fd_ioctl, + .providergone = fd_providergone, }; static int @@ -1413,7 +1416,6 @@ struct fd_data *fd; struct fdc_data *fdc; int ar, aw, ae; - int busy; fd = pp->geom->softc; fdc = fd->fdc; @@ -1431,11 +1433,9 @@ if (ar == 0 && aw == 0 && ae == 0) { fd->options &= ~(FDOPT_NORETRY | FDOPT_NOERRLOG | FDOPT_NOERROR); - device_unbusy(fd->dev); return (0); } - busy = 0; if (pp->acr == 0 && pp->acw == 0 && pp->ace == 0) { if (fdmisccmd(fd, BIO_PROBE, NULL)) return (ENXIO); @@ -1453,13 +1453,9 @@ fd->flags &= ~FD_NEWDISK; mtx_unlock(&fdc->fdc_mtx); } - device_busy(fd->dev); - busy = 1; } if (w > 0 && (fd->flags & FD_WP)) { - if (busy) - device_unbusy(fd->dev); return (EROFS); } @@ -1588,8 +1584,6 @@ return (error); }; - - /* * Configuration/initialization stuff, per controller. */ @@ -2055,6 +2049,16 @@ return (0); } +static void +fd_providergone(struct g_provider *pp) +{ + struct fd_data *fd; + + fd = pp->geom->softc; + fd->gone = true; + wakeup(fd); +} + static void fd_detach_geom(void *arg, int flag) { @@ -2071,9 +2075,10 @@ fd = device_get_softc(dev); g_waitfor_event(fd_detach_geom, fd, M_WAITOK, NULL); - while (device_get_state(dev) == DS_BUSY) - tsleep(fd, PZERO, "fdd", hz/10); - callout_drain(&fd->toffhandle); + callout_drain(&fd->toffhandle); /* fdc_detach turns off motor */ + while (!fd->gone) { + tsleep(fd, PZERO, "fdgone", hz/10); + } return (0); }