diff options
author | imp <imp@FreeBSD.org> | 2004-09-08 07:13:39 +0000 |
---|---|---|
committer | imp <imp@FreeBSD.org> | 2004-09-08 07:13:39 +0000 |
commit | 772c5279be6bb55eca2f8e98e29a8f725c93c01d (patch) | |
tree | 2e40698989b5286855dc397e72aabc95258aa972 | |
parent | 5448c0081f6becd3cd346fd62d2e6738435069cc (diff) | |
download | FreeBSD-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.c | 20 |
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); } |