summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorjoe <joe@FreeBSD.org>2002-07-10 00:52:16 +0000
committerjoe <joe@FreeBSD.org>2002-07-10 00:52:16 +0000
commitfc5bd37837df455e4f71d8c9572c7c64bc2aa428 (patch)
treedabf42f149c75bc3e129e29be91d51a43089f7e3 /sys
parent2ff4d14a63182efbf9af081cf24121a59d933c2e (diff)
downloadFreeBSD-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.c55
-rw-r--r--sys/dev/usb/uplcom.c2
-rw-r--r--sys/dev/usb/uvscom.c10
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);
}
}
OpenPOWER on IntegriCloud