summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/dev/usb/usb_dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/dev/usb/usb_dev.c')
-rw-r--r--freebsd/sys/dev/usb/usb_dev.c33
1 files changed, 18 insertions, 15 deletions
diff --git a/freebsd/sys/dev/usb/usb_dev.c b/freebsd/sys/dev/usb/usb_dev.c
index 3ff064ee..ce107cf3 100644
--- a/freebsd/sys/dev/usb/usb_dev.c
+++ b/freebsd/sys/dev/usb/usb_dev.c
@@ -292,11 +292,15 @@ error:
usbd_enum_unlock(cpd->udev);
if (crd->is_uref) {
- cpd->udev->refcount--;
- cv_broadcast(&cpd->udev->ref_cv);
+ if (--(cpd->udev->refcount) == 0)
+ cv_broadcast(&cpd->udev->ref_cv);
}
mtx_unlock(&usb_ref_lock);
DPRINTFN(2, "fail\n");
+
+ /* clear all refs */
+ memset(crd, 0, sizeof(*crd));
+
return (USB_ERR_INVAL);
}
@@ -360,8 +364,8 @@ usb_unref_device(struct usb_cdev_privdata *cpd,
}
if (crd->is_uref) {
crd->is_uref = 0;
- cpd->udev->refcount--;
- cv_broadcast(&cpd->udev->ref_cv);
+ if (--(cpd->udev->refcount) == 0)
+ cv_broadcast(&cpd->udev->ref_cv);
}
mtx_unlock(&usb_ref_lock);
}
@@ -587,12 +591,12 @@ usb_fifo_free(struct usb_fifo *f)
/* decrease refcount */
f->refcount--;
- /* prevent any write flush */
- f->flag_iserror = 1;
/* need to wait until all callers have exited */
while (f->refcount != 0) {
mtx_unlock(&usb_ref_lock); /* avoid LOR */
mtx_lock(f->priv_mtx);
+ /* prevent write flush, if any */
+ f->flag_iserror = 1;
/* get I/O thread out of any sleep state */
if (f->flag_sleeping) {
f->flag_sleeping = 0;
@@ -1092,8 +1096,8 @@ usb_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int fflag, struct thread*
goto done;
if (usb_usb_ref_device(cpd, &refs)) {
- err = ENXIO;
- goto done;
+ /* we lost the reference */
+ return (ENXIO);
}
err = (f->methods->f_ioctl_post) (f, cmd, addr, fflags);
@@ -1116,9 +1120,8 @@ usb_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int fflag, struct thread*
while (usb_ref_device(cpd, &refs, 1 /* need uref */)) {
if (usb_ref_device(cpd, &refs, 0)) {
- /* device no longer exits */
- err = ENXIO;
- goto done;
+ /* device no longer exists */
+ return (ENXIO);
}
usb_unref_device(cpd, &refs);
usb_pause_mtx(NULL, hz / 128);
@@ -1410,9 +1413,9 @@ usb_read(struct cdev *dev, struct uio *uio, int ioflag)
return (err);
err = usb_ref_device(cpd, &refs, 0 /* no uref */ );
- if (err) {
+ if (err)
return (ENXIO);
- }
+
fflags = cpd->fflags;
f = refs.rxfifo;
@@ -1536,9 +1539,9 @@ usb_write(struct cdev *dev, struct uio *uio, int ioflag)
return (err);
err = usb_ref_device(cpd, &refs, 0 /* no uref */ );
- if (err) {
+ if (err)
return (ENXIO);
- }
+
fflags = cpd->fflags;
f = refs.txfifo;