Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/gpio/gpiopps.c
Show First 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | |||||
static int | static int | ||||
gpiopps_open(struct cdev *dev, int flags, int fmt, struct thread *td) | gpiopps_open(struct cdev *dev, int flags, int fmt, struct thread *td) | ||||
{ | { | ||||
struct pps_softc *sc = dev->si_drv1; | struct pps_softc *sc = dev->si_drv1; | ||||
/* We can't be unloaded while open, so mark ourselves BUSY. */ | /* We can't be unloaded while open, so mark ourselves BUSY. */ | ||||
mtx_lock(&sc->pps_mtx); | 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); | mtx_unlock(&sc->pps_mtx); | ||||
return 0; | return 0; | ||||
} | } | ||||
static int | static int | ||||
gpiopps_close(struct cdev *dev, int flags, int fmt, struct thread *td) | gpiopps_close(struct cdev *dev, int flags, int fmt, struct thread *td) | ||||
{ | { | ||||
struct pps_softc *sc = dev->si_drv1; | 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); | mtx_lock(&sc->pps_mtx); | ||||
device_unbusy(sc->dev); | device_unbusy(sc->dev); | ||||
mtx_unlock(&sc->pps_mtx); | mtx_unlock(&sc->pps_mtx); | ||||
return 0; | return 0; | ||||
} | } | ||||
static int | static int | ||||
gpiopps_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, struct thread *td) | gpiopps_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, struct thread *td) | ||||
{ | { | ||||
struct pps_softc *sc = dev->si_drv1; | struct pps_softc *sc = dev->si_drv1; | ||||
int err; | int err; | ||||
/* Let the kernel do the heavy lifting for ioctl. */ | /* Let the kernel do the heavy lifting for ioctl. */ | ||||
mtx_lock(&sc->pps_mtx); | mtx_lock(&sc->pps_mtx); | ||||
err = pps_ioctl(cmd, data, &sc->pps_state); | err = pps_ioctl(cmd, data, &sc->pps_state); | ||||
mtx_unlock(&sc->pps_mtx); | mtx_unlock(&sc->pps_mtx); | ||||
return err; | return err; | ||||
} | } | ||||
static struct cdevsw pps_cdevsw = { | static struct cdevsw pps_cdevsw = { | ||||
.d_version = D_VERSION, | .d_version = D_VERSION, | ||||
.d_flags = D_TRACKCLOSE, | |||||
jhb: Note that this only sort of works, and that really one has to use cdevpriv(9) to be fully safe… | |||||
Done Inline ActionsThere's half a dozen or so drivers in the tree that use a similar trick. I'd like to leave this in this commit and address those in a separate commit. imp: There's half a dozen or so drivers in the tree that use a similar trick. I'd like to leave this… | |||||
.d_open = gpiopps_open, | .d_open = gpiopps_open, | ||||
.d_close = gpiopps_close, | .d_close = gpiopps_close, | ||||
.d_ioctl = gpiopps_ioctl, | .d_ioctl = gpiopps_ioctl, | ||||
.d_name = PPS_CDEV_NAME, | .d_name = PPS_CDEV_NAME, | ||||
}; | }; | ||||
static int | static int | ||||
gpiopps_ifltr(void *arg) | gpiopps_ifltr(void *arg) | ||||
▲ Show 20 Lines • Show All 172 Lines • Show Last 20 Lines |
Note that this only sort of works, and that really one has to use cdevpriv(9) to be fully safe here (you would do the device_unbusy in the cdevpriv dtor). There are some edge cases when open() is not paired with close even in the D_TRACKCLOSE case.