summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2004-09-08 07:13:39 +0000
committerimp <imp@FreeBSD.org>2004-09-08 07:13:39 +0000
commit772c5279be6bb55eca2f8e98e29a8f725c93c01d (patch)
tree2e40698989b5286855dc397e72aabc95258aa972
parent5448c0081f6becd3cd346fd62d2e6738435069cc (diff)
downloadFreeBSD-src-772c5279be6bb55eca2f8e98e29a8f725c93c01d.zip
FreeBSD-src-772c5279be6bb55eca2f8e98e29a8f725c93c01d.tar.gz
Back out 1.88.
The reference counts are there to block detach until the sleepers in read/write/ioctl have gotten out, not to prevent the open device from going away. Restore the old behavior so that we have a chance to wake up sleepers when the usb device goes away, so they can properly return EIO back to the caller when this happens. Otherwise, we have a guarnateed panic waiting to happen when a device detaches with an active read channel. This should be merged to 5 asap.
-rw-r--r--sys/dev/usb/ugen.c20
1 files changed, 11 insertions, 9 deletions
diff --git a/sys/dev/usb/ugen.c b/sys/dev/usb/ugen.c
index 4ff006f..760cc6a 100644
--- a/sys/dev/usb/ugen.c
+++ b/sys/dev/usb/ugen.c
@@ -405,7 +405,6 @@ ugenopen(struct cdev *dev, int flag, int mode, usb_proc_ptr p)
if (endpt == USB_CONTROL_ENDPOINT) {
sc->sc_is_open[USB_CONTROL_ENDPOINT] = 1;
- sc->sc_refcnt++;
return (0);
}
@@ -516,7 +515,6 @@ ugenopen(struct cdev *dev, int flag, int mode, usb_proc_ptr p)
}
}
sc->sc_is_open[endpt] = 1;
- sc->sc_refcnt++;
return (0);
}
@@ -544,8 +542,6 @@ ugenclose(struct cdev *dev, int flag, int mode, usb_proc_ptr p)
if (endpt == USB_CONTROL_ENDPOINT) {
DPRINTFN(5, ("ugenclose: close control\n"));
sc->sc_is_open[endpt] = 0;
- if (--sc->sc_refcnt == 0)
- usb_detach_wakeup(USBDEV(sc->sc_dev));
return (0);
}
@@ -581,8 +577,6 @@ ugenclose(struct cdev *dev, int flag, int mode, usb_proc_ptr p)
}
}
sc->sc_is_open[endpt] = 0;
- if (--sc->sc_refcnt == 0)
- usb_detach_wakeup(USBDEV(sc->sc_dev));
return (0);
}
@@ -739,7 +733,10 @@ ugenread(struct cdev *dev, struct uio *uio, int flag)
USB_GET_SC(ugen, UGENUNIT(dev), sc);
+ sc->sc_refcnt++;
error = ugen_do_read(sc, endpt, uio, flag);
+ if (--sc->sc_refcnt < 0)
+ usb_detach_wakeup(USBDEV(sc->sc_dev));
return (error);
}
@@ -836,7 +833,10 @@ ugenwrite(struct cdev *dev, struct uio *uio, int flag)
USB_GET_SC(ugen, UGENUNIT(dev), sc);
+ sc->sc_refcnt++;
error = ugen_do_write(sc, endpt, uio, flag);
+ if (--sc->sc_refcnt < 0)
+ usb_detach_wakeup(USBDEV(sc->sc_dev));
return (error);
}
@@ -885,13 +885,12 @@ USB_DETACH(ugen)
}
s = splusb();
- if (sc->sc_refcnt > 0) {
+ if (--sc->sc_refcnt >= 0) {
/* Wake everyone */
for (i = 0; i < USB_MAX_ENDPOINTS; i++)
wakeup(&sc->sc_endpoints[i][IN]);
/* Wait for processes to go away. */
- while (sc->sc_refcnt > 0)
- usb_detach_wait(USBDEV(sc->sc_dev));
+ usb_detach_wait(USBDEV(sc->sc_dev));
}
splx(s);
@@ -1401,7 +1400,10 @@ ugenioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, usb_proc_ptr p)
USB_GET_SC(ugen, UGENUNIT(dev), sc);
+ sc->sc_refcnt++;
error = ugen_do_ioctl(sc, endpt, cmd, addr, flag, p);
+ if (--sc->sc_refcnt < 0)
+ usb_detach_wakeup(USBDEV(sc->sc_dev));
return (error);
}
OpenPOWER on IntegriCloud