diff options
author | joe <joe@FreeBSD.org> | 2002-07-10 00:52:16 +0000 |
---|---|---|
committer | joe <joe@FreeBSD.org> | 2002-07-10 00:52:16 +0000 |
commit | fc5bd37837df455e4f71d8c9572c7c64bc2aa428 (patch) | |
tree | dabf42f149c75bc3e129e29be91d51a43089f7e3 /sys | |
parent | 2ff4d14a63182efbf9af081cf24121a59d933c2e (diff) | |
download | FreeBSD-src-fc5bd37837df455e4f71d8c9572c7c64bc2aa428.zip FreeBSD-src-fc5bd37837df455e4f71d8c9572c7c64bc2aa428.tar.gz |
Improve detach operation.
Submitted by: akiyama
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/usb/ucom.c | 55 | ||||
-rw-r--r-- | sys/dev/usb/uplcom.c | 2 | ||||
-rw-r--r-- | sys/dev/usb/uvscom.c | 10 |
3 files changed, 53 insertions, 14 deletions
diff --git a/sys/dev/usb/ucom.c b/sys/dev/usb/ucom.c index 4aac9b88..3928e7c 100644 --- a/sys/dev/usb/ucom.c +++ b/sys/dev/usb/ucom.c @@ -204,6 +204,9 @@ ucom_attach(struct ucom_softc *sc) int ucom_detach(struct ucom_softc *sc) { + struct tty *tp = sc->sc_tty; + int s; + DPRINTF(("ucom_detach: sc = %p, tp = %p\n", sc, sc->sc_tty)); sc->sc_dying = 1; @@ -213,11 +216,28 @@ ucom_detach(struct ucom_softc *sc) if (sc->sc_bulkout_pipe != NULL) usbd_abort_pipe(sc->sc_bulkout_pipe); - if (sc->sc_tty == NULL) { + if (tp != NULL) { + if (tp->t_state & TS_ISOPEN) { + device_printf(sc->sc_dev, + "still open, focing close\n"); + (*linesw[tp->t_line].l_close)(tp, 0); + tp->t_gen++; + ttyclose(tp); + ttwakeup(tp); + ttwwakeup(tp); + } + } else { DPRINTF(("ucom_detach: no tty\n")); return (0); } + s = splusb(); + if (--sc->sc_refcnt >= 0) { + /* Wait for processes to go away. */ + usb_detach_wait(USBDEV(sc->sc_dev)); + } + splx(s); + destroy_dev(sc->dev); return (0); @@ -252,7 +272,7 @@ ucomopen(dev_t dev, int flag, int mode, usb_proc_ptr p) USB_GET_SC_OPEN(ucom, unit, sc); if (sc->sc_dying) - return (EIO); + return (ENXIO); tp = sc->sc_tty; @@ -373,8 +393,8 @@ ucomopen(dev_t dev, int flag, int mode, usb_proc_ptr p) /* * Handle initial DCD. */ - if (ISSET(sc->sc_msr, UMSR_DCD) - || (minor(dev) & UCOM_CALLOUT_MASK)) + if (ISSET(sc->sc_msr, UMSR_DCD) || + (minor(dev) & UCOM_CALLOUT_MASK)) (*linesw[tp->t_line].l_modem)(tp, 1); ucomstartread(sc); @@ -397,6 +417,7 @@ ucomopen(dev_t dev, int flag, int mode, usb_proc_ptr p) DPRINTF(("%s: ucomopen: success\n", USBDEVNAME(sc->sc_dev))); sc->sc_poll = 1; + sc->sc_refcnt++; return (0); @@ -447,7 +468,7 @@ ucomclose(dev_t dev, int flag, int mode, usb_proc_ptr p) USBDEVNAME(sc->sc_dev), UCOMUNIT(dev))); if (!ISSET(tp->t_state, TS_ISOPEN)) - return (0); + goto quit; s = spltty(); (*linesw[tp->t_line].l_close)(tp, flag); @@ -456,7 +477,7 @@ ucomclose(dev_t dev, int flag, int mode, usb_proc_ptr p) splx(s); if (sc->sc_dying) - return (0); + goto quit; if (!ISSET(tp->t_state, TS_ISOPEN)) { /* @@ -470,6 +491,10 @@ ucomclose(dev_t dev, int flag, int mode, usb_proc_ptr p) if (sc->sc_callback->ucom_close != NULL) sc->sc_callback->ucom_close(sc->sc_parent, sc->sc_portno); + quit: + if (--sc->sc_refcnt < 0) + usb_detach_wakeup(USBDEV(sc->sc_dev)); + return (0); } @@ -927,6 +952,8 @@ ucomstop(struct tty *tp, int flag) } splx(s); } + + DPRINTF(("ucomstop: done\n")); } Static void @@ -1106,12 +1133,24 @@ ucom_cleanup(struct ucom_softc *sc) Static void ucomstopread(struct ucom_softc *sc) { + usbd_status err; + + DPRINTF(("ucomstopread: enter\n")); + if (!(sc->sc_state & UCS_RXSTOP)) { - if (sc->sc_bulkin_pipe == NULL) + if (sc->sc_bulkin_pipe == NULL) { + DPRINTF(("ucomstopread: bulkin pipe NULL\n")); return; + } sc->sc_state |= UCS_RXSTOP; - usbd_abort_pipe(sc->sc_bulkin_pipe); + err = usbd_abort_pipe(sc->sc_bulkin_pipe); + if (err) { + DPRINTF(("ucomstopread: err = %s\n", + usbd_errstr(err))); + } } + + DPRINTF(("ucomstopread: leave\n")); } static void diff --git a/sys/dev/usb/uplcom.c b/sys/dev/usb/uplcom.c index fe1ec1f..2da6f8d 100644 --- a/sys/dev/usb/uplcom.c +++ b/sys/dev/usb/uplcom.c @@ -680,7 +680,7 @@ uplcom_open(void *addr, int portno) int err; if (sc->sc_ucom.sc_dying) - return (EIO); + return (ENXIO); DPRINTF(("uplcom_open: sc = %p\n", sc)); diff --git a/sys/dev/usb/uvscom.c b/sys/dev/usb/uvscom.c index 312ee9f..7d38792 100644 --- a/sys/dev/usb/uvscom.c +++ b/sys/dev/usb/uvscom.c @@ -712,7 +712,7 @@ uvscom_open(void *addr, int portno) int i; if (sc->sc_ucom.sc_dying) - return (EIO); + return (ENXIO); DPRINTF(("uvscom_open: sc = %p\n", sc)); @@ -725,7 +725,7 @@ uvscom_open(void *addr, int portno) if (err) { DPRINTF(("%s: uvscom_open: readstat faild\n", USBDEVNAME(sc->sc_ucom.sc_dev))); - return (EIO); + return (ENXIO); } sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK); @@ -742,7 +742,7 @@ uvscom_open(void *addr, int portno) printf("%s: cannot open interrupt pipe (addr %d)\n", USBDEVNAME(sc->sc_ucom.sc_dev), sc->sc_intr_number); - return (EIO); + return (ENXIO); } } else { DPRINTF(("uvscom_open: did not open interrupt pipe.\n")); @@ -759,14 +759,14 @@ uvscom_open(void *addr, int portno) if (i == 0) { DPRINTF(("%s: unit is not ready\n", USBDEVNAME(sc->sc_ucom.sc_dev))); - return (EIO); + return (ENXIO); } /* check PC card was inserted */ if (ISSET(sc->sc_usr, UVSCOM_NOCARD)) { DPRINTF(("%s: no card\n", USBDEVNAME(sc->sc_ucom.sc_dev))); - return (EIO); + return (ENXIO); } } |