Page MenuHomeFreeBSD

D47951.diff
No OneTemporary

D47951.diff

diff --git a/sys/dev/usb/serial/usb_serial.c b/sys/dev/usb/serial/usb_serial.c
--- a/sys/dev/usb/serial/usb_serial.c
+++ b/sys/dev/usb/serial/usb_serial.c
@@ -599,6 +599,7 @@
{
struct ucom_super_softc *ssc = sc->sc_super;
struct ucom_param_task *task;
+ int error;
UCOM_MTX_ASSERT(sc, MA_OWNED);
@@ -628,8 +629,15 @@
/*
* Closing or opening the device should be synchronous.
*/
- if (fn == ucom_cfg_close || fn == ucom_cfg_open)
- usb_proc_mwait(&ssc->sc_tq, t0, t1);
+ if (fn == ucom_cfg_close || fn == ucom_cfg_open) {
+ error = usb_proc_mwait_sig(&ssc->sc_tq, t0, t1);
+
+ /* usb_proc_mwait_sig may have dropped the tty lock. */
+ if (error == 0 && sc->sc_tty != NULL && tty_gone(sc->sc_tty))
+ error = ENXIO;
+ } else {
+ error = 0;
+ }
/*
* In case of multiple configure requests,
@@ -638,7 +646,7 @@
if (fn == ucom_cfg_start_transfers)
sc->sc_last_start_xfer = &task->hdr;
- return (0);
+ return (error);
}
static void
diff --git a/sys/dev/usb/usb_process.h b/sys/dev/usb/usb_process.h
--- a/sys/dev/usb/usb_process.h
+++ b/sys/dev/usb/usb_process.h
@@ -76,6 +76,7 @@
const char *pmesg, uint8_t prio);
void usb_proc_drain(struct usb_process *up);
void usb_proc_mwait(struct usb_process *up, void *pm0, void *pm1);
+int usb_proc_mwait_sig(struct usb_process *up, void *pm0, void *pm1);
void usb_proc_free(struct usb_process *up);
void *usb_proc_msignal(struct usb_process *up, void *pm0, void *pm1);
void usb_proc_rewakeup(struct usb_process *up);
diff --git a/sys/dev/usb/usb_process.c b/sys/dev/usb/usb_process.c
--- a/sys/dev/usb/usb_process.c
+++ b/sys/dev/usb/usb_process.c
@@ -361,25 +361,21 @@
return (0);
}
-/*------------------------------------------------------------------------*
- * usb_proc_mwait
- *
- * This function will return when the USB process message pointed to
- * by "pm" is no longer on a queue. This function must be called
- * having "up->up_mtx" locked.
- *------------------------------------------------------------------------*/
-void
-usb_proc_mwait(struct usb_process *up, void *_pm0, void *_pm1)
+static int
+usb_proc_mwait_impl(struct usb_process *up, void *_pm0, void *_pm1,
+ bool interruptible)
{
struct usb_proc_msg *pm0 = _pm0;
struct usb_proc_msg *pm1 = _pm1;
+ int error;
/* check if gone */
if (up->up_gone)
- return;
+ return (ENXIO);
USB_MTX_ASSERT(up->up_mtx, MA_OWNED);
+ error = 0;
if (up->up_curtd == curthread) {
/* Just remove the messages from the queue. */
if (pm0->pm_qentry.tqe_prev) {
@@ -391,14 +387,59 @@
pm1->pm_qentry.tqe_prev = NULL;
}
} else
- while (pm0->pm_qentry.tqe_prev ||
- pm1->pm_qentry.tqe_prev) {
+ while (error == 0 && (pm0->pm_qentry.tqe_prev ||
+ pm1->pm_qentry.tqe_prev)) {
/* check if config thread is gone */
if (up->up_gone)
- break;
+ return (ENXIO);
up->up_dsleep = 1;
- cv_wait(&up->up_drain, up->up_mtx);
+ if (interruptible) {
+ error = cv_wait_sig(&up->up_drain, up->up_mtx);
+
+ /*
+ * The fact that we were interrupted doesn't
+ * matter if our goal was accomplished anyways.
+ */
+ if (error != 0 && !USB_PROC_MSG_ENQUEUED(pm0) &&
+ !USB_PROC_MSG_ENQUEUED(pm1))
+ error = 0;
+ } else {
+ cv_wait(&up->up_drain, up->up_mtx);
+ }
}
+
+ if (error == ERESTART)
+ error = EINTR;
+ return (error);
+}
+
+/*------------------------------------------------------------------------*
+ * usb_proc_mwait
+ *
+ * This function will return when the USB process message pointed to
+ * by "pm" is no longer on a queue. This function must be called
+ * having "up->up_mtx" locked.
+ *------------------------------------------------------------------------*/
+void
+usb_proc_mwait(struct usb_process *up, void *_pm0, void *_pm1)
+{
+
+ (void)usb_proc_mwait_impl(up, _pm0, _pm1, false);
+}
+
+/*------------------------------------------------------------------------*
+ * usb_proc_mwait_sig
+ *
+ * This function will return when the USB process message pointed to
+ * by "pm" is no longer on a queue. This function must be called
+ * having "up->up_mtx" locked. This version of usb_proc_mwait is
+ * interruptible.
+ *------------------------------------------------------------------------*/
+int
+usb_proc_mwait_sig(struct usb_process *up, void *_pm0, void *_pm1)
+{
+
+ return (usb_proc_mwait_impl(up, _pm0, _pm1, true));
}
/*------------------------------------------------------------------------*
diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h
--- a/sys/dev/usb/usbdi.h
+++ b/sys/dev/usb/usbdi.h
@@ -525,6 +525,8 @@
usb_size_t pm_num;
};
+#define USB_PROC_MSG_ENQUEUED(msg) ((msg)->pm_qentry.tqe_prev != NULL)
+
#define USB_FIFO_TX 0
#define USB_FIFO_RX 1

File Metadata

Mime Type
text/plain
Expires
Fri, Feb 14, 1:28 PM (21 h, 22 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16643098
Default Alt Text
D47951.diff (4 KB)

Event Timeline