Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F110094848
D47951.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D47951.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D47951: usb: serial: allow the open/close sleep to be interruptible
Attached
Detach File
Event Timeline
Log In to Comment