diff --git a/sys/dev/drm2/drm_fops.c b/sys/dev/drm2/drm_fops.c --- a/sys/dev/drm2/drm_fops.c +++ b/sys/dev/drm2/drm_fops.c @@ -157,9 +157,7 @@ return 0; err_undo: - mtx_lock(&Giant); /* FIXME: Giant required? */ device_unbusy(dev->dev); - mtx_unlock(&Giant); dev->open_count--; sx_xunlock(&drm_global_mutex); return -retcode; @@ -273,9 +271,7 @@ list_add(&priv->lhead, &dev->filelist); DRM_UNLOCK(dev); - mtx_lock(&Giant); /* FIXME: Giant required? */ device_busy(dev->dev); - mtx_unlock(&Giant); ret = devfs_set_cdevpriv(priv, drm_release); if (ret != 0) @@ -453,9 +449,7 @@ */ atomic_inc(&dev->counts[_DRM_STAT_CLOSES]); - mtx_lock(&Giant); device_unbusy(dev->dev); - mtx_unlock(&Giant); if (!--dev->open_count) { if (atomic_read(&dev->ioctl_count)) { DRM_ERROR("Device busy: %d\n", diff --git a/sys/dev/gpio/gpiopps.c b/sys/dev/gpio/gpiopps.c --- a/sys/dev/gpio/gpiopps.c +++ b/sys/dev/gpio/gpiopps.c @@ -73,9 +73,7 @@ /* We can't be unloaded while open, so mark ourselves BUSY. */ mtx_lock(&sc->pps_mtx); - if (device_get_state(sc->dev) < DS_BUSY) { - device_busy(sc->dev); - } + device_busy(sc->dev); mtx_unlock(&sc->pps_mtx); return 0; @@ -86,10 +84,6 @@ { struct pps_softc *sc = dev->si_drv1; - /* - * Un-busy on last close. We rely on the vfs counting stuff to only call - * this routine on last-close, so we don't need any open-count logic. - */ mtx_lock(&sc->pps_mtx); device_unbusy(sc->dev); mtx_unlock(&sc->pps_mtx); @@ -113,6 +107,7 @@ static struct cdevsw pps_cdevsw = { .d_version = D_VERSION, + .d_flags = D_TRACKCLOSE, .d_open = gpiopps_open, .d_close = gpiopps_close, .d_ioctl = gpiopps_ioctl, diff --git a/sys/dev/pccard/pccard.c b/sys/dev/pccard/pccard.c --- a/sys/dev/pccard/pccard.c +++ b/sys/dev/pccard/pccard.c @@ -342,7 +342,7 @@ if (pf->dev == NULL) continue; state = device_get_state(pf->dev); - if (state == DS_ATTACHED || state == DS_BUSY) + if (state == DS_ATTACHED) device_detach(pf->dev); if (pf->cfe != NULL) pccard_function_disable(pf); diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c --- a/sys/kern/subr_bus.c +++ b/sys/kern/subr_bus.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -140,7 +141,7 @@ int unit; /**< current unit number */ char* nameunit; /**< name+unit e.g. foodev0 */ char* desc; /**< driver specific description */ - int busy; /**< count of calls to device_busy() */ + u_int busy; /**< count of calls to device_busy() */ device_state_t state; /**< current device state */ uint32_t devflags; /**< api level flags for device_get_flags() */ u_int flags; /**< internal device flags */ @@ -2634,13 +2635,13 @@ void device_busy(device_t dev) { - if (dev->state < DS_ATTACHING) - panic("device_busy: called for unattached device"); - if (dev->busy == 0 && dev->parent) + + /* + * Mark the device as busy, recursively up the tree if this busy count + * goes 0->1. + */ + if (refcount_acquire(&dev->busy) == 0 && dev->parent != NULL) device_busy(dev->parent); - dev->busy++; - if (dev->state == DS_ATTACHED) - dev->state = DS_BUSY; } /** @@ -2649,17 +2650,12 @@ void device_unbusy(device_t dev) { - if (dev->busy != 0 && dev->state != DS_BUSY && - dev->state != DS_ATTACHING) - panic("device_unbusy: called for non-busy device %s", - device_get_nameunit(dev)); - dev->busy--; - if (dev->busy == 0) { - if (dev->parent) - device_unbusy(dev->parent); - if (dev->state == DS_BUSY) - dev->state = DS_ATTACHED; - } + + /* + * Mark the device as unbsy, recursively if this is the last busy count. + */ + if (refcount_release(&dev->busy) && dev->parent != NULL) + device_unbusy(dev->parent); } /** @@ -3004,10 +3000,7 @@ attachentropy = (uint16_t)(get_cyclecount() - attachtime); random_harvest_direct(&attachentropy, sizeof(attachentropy), RANDOM_ATTACH); device_sysctl_update(dev); - if (dev->busy) - dev->state = DS_BUSY; - else - dev->state = DS_ATTACHED; + dev->state = DS_ATTACHED; dev->flags &= ~DF_DONENOMATCH; EVENTHANDLER_DIRECT_INVOKE(device_attach, dev); devadded(dev); @@ -3038,7 +3031,7 @@ GIANT_REQUIRED; PDEBUG(("%s", DEVICENAME(dev))); - if (dev->state == DS_BUSY) + if (dev->busy > 0) return (EBUSY); if (dev->state == DS_ATTACHING) { device_printf(dev, "device in attaching state! Deferring detach.\n"); @@ -3090,7 +3083,7 @@ device_quiesce(device_t dev) { PDEBUG(("%s", DEVICENAME(dev))); - if (dev->state == DS_BUSY) + if (dev->busy > 0) return (EBUSY); if (dev->state != DS_ATTACHED) return (0); diff --git a/sys/sys/bus.h b/sys/sys/bus.h --- a/sys/sys/bus.h +++ b/sys/sys/bus.h @@ -58,7 +58,6 @@ DS_ALIVE = 20, /**< @brief probe succeeded */ DS_ATTACHING = 25, /**< @brief currently attaching */ DS_ATTACHED = 30, /**< @brief attach method called */ - DS_BUSY = 40 /**< @brief device is open */ } device_state_t; /**