From 63ba42fbf5f6d4ea1a0c650715049b02cde4a6cf Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Wed, 8 Sep 2004 07:13:39 +0000 Subject: 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. --- sys/dev/usb/ugen.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/sys/dev/usb/ugen.c b/sys/dev/usb/ugen.c index 4ff006f9311af..760cc6a79535a 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); } -- cgit v1.3