Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F115547408
D47952.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
D47952.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
@@ -153,7 +153,7 @@
static void ucom_detach_tty(struct ucom_super_softc *, struct ucom_softc *);
static int ucom_queue_command(struct ucom_softc *,
usb_proc_callback_t *, struct termios *pt,
- struct usb_proc_msg *t0, struct usb_proc_msg *t1);
+ struct usb_proc_msg *t0, struct usb_proc_msg *t1, bool wait);
static void ucom_shutdown(struct ucom_softc *);
static void ucom_ring(struct ucom_softc *, uint8_t);
static void ucom_break(struct ucom_softc *, uint8_t);
@@ -592,10 +592,43 @@
}
}
+static void
+ucom_command_barrier_cb(struct usb_proc_msg *msg __unused)
+{
+ /* NOP */
+}
+
+/*
+ * ucom_command_barrier inserts a dummy task and waits for it so that we can be
+ * certain that previously enqueued tasks are finished before returning back to
+ * the tty layer.
+ */
+static int
+ucom_command_barrier(struct ucom_softc *sc)
+{
+ struct ucom_super_softc *ssc = sc->sc_super;
+ struct usb_proc_msg dummy = { .pm_callback = ucom_command_barrier_cb };
+ struct usb_proc_msg *task;
+ int error;
+
+ UCOM_MTX_ASSERT(sc, MA_OWNED);
+
+ if (usb_proc_is_gone(&ssc->sc_tq)) {
+ DPRINTF("proc is gone\n");
+ return (ENXIO); /* nothing to do */
+ }
+
+ task = usb_proc_msignal(&ssc->sc_tq, &dummy, &dummy);
+ error = usb_proc_mwait_sig(&ssc->sc_tq, task, task);
+ if (error == 0 && sc->sc_tty != NULL && tty_gone(sc->sc_tty))
+ error = ENXIO;
+ return (error);
+}
+
static int
ucom_queue_command(struct ucom_softc *sc,
usb_proc_callback_t *fn, struct termios *pt,
- struct usb_proc_msg *t0, struct usb_proc_msg *t1)
+ struct usb_proc_msg *t0, struct usb_proc_msg *t1, bool wait)
{
struct ucom_super_softc *ssc = sc->sc_super;
struct ucom_param_task *task;
@@ -629,7 +662,7 @@
/*
* Closing or opening the device should be synchronous.
*/
- if (fn == ucom_cfg_close || fn == ucom_cfg_open) {
+ if (wait) {
error = usb_proc_mwait_sig(&ssc->sc_tq, t0, t1);
/* usb_proc_mwait_sig may have dropped the tty lock. */
@@ -793,14 +826,17 @@
error = ucom_queue_command(sc, ucom_cfg_open, NULL,
&sc->sc_open_task[0].hdr,
- &sc->sc_open_task[1].hdr);
+ &sc->sc_open_task[1].hdr, true);
if (error != 0)
goto out;
- /* Queue transfer enable command last */
+ /*
+ * Queue transfer enable command last, we'll have a barrier later so we
+ * don't need to wait on this to complete specifically.
+ */
error = ucom_queue_command(sc, ucom_cfg_start_transfers, NULL,
&sc->sc_start_task[0].hdr,
- &sc->sc_start_task[1].hdr);
+ &sc->sc_start_task[1].hdr, true);
if (error != 0)
goto out;
@@ -813,6 +849,7 @@
ucom_status_change(sc);
+ error = ucom_command_barrier(sc);
out:
return (error);
}
@@ -852,7 +889,7 @@
(void)ucom_queue_command(sc, ucom_cfg_close, NULL,
&sc->sc_close_task[0].hdr,
- &sc->sc_close_task[1].hdr);
+ &sc->sc_close_task[1].hdr, true);
sc->sc_flag &= ~(UCOM_FLAG_HL_READY | UCOM_FLAG_RTS_IFLOW);
@@ -933,11 +970,15 @@
#endif
case TIOCSBRK:
ucom_break(sc, 1);
- error = 0;
+ error = ucom_command_barrier(sc);
+ if (error == ENXIO)
+ error = ENODEV;
break;
case TIOCCBRK:
ucom_break(sc, 0);
- error = 0;
+ error = ucom_command_barrier(sc);
+ if (error == ENXIO)
+ error = ENODEV;
break;
default:
if (sc->sc_callback->ucom_ioctl) {
@@ -1097,7 +1138,7 @@
*/
(void)ucom_queue_command(sc, ucom_cfg_line_state, NULL,
&sc->sc_line_state_task[0].hdr,
- &sc->sc_line_state_task[1].hdr);
+ &sc->sc_line_state_task[1].hdr, false);
}
static void
@@ -1255,7 +1296,7 @@
(void)ucom_queue_command(sc, ucom_cfg_status_change, NULL,
&sc->sc_status_task[0].hdr,
- &sc->sc_status_task[1].hdr);
+ &sc->sc_status_task[1].hdr, true);
}
static void
@@ -1329,14 +1370,14 @@
/* Queue baud rate programming command first */
error = ucom_queue_command(sc, ucom_cfg_param, t,
&sc->sc_param_task[0].hdr,
- &sc->sc_param_task[1].hdr);
+ &sc->sc_param_task[1].hdr, true);
if (error != 0)
goto done;
/* Queue transfer enable command last */
error = ucom_queue_command(sc, ucom_cfg_start_transfers, NULL,
&sc->sc_start_task[0].hdr,
- &sc->sc_start_task[1].hdr);
+ &sc->sc_start_task[1].hdr, true);
if (error != 0)
goto done;
@@ -1346,6 +1387,8 @@
sc->sc_flag &= ~UCOM_FLAG_RTS_IFLOW;
ucom_modem(tp, SER_RTS, 0);
}
+
+ error = ucom_command_barrier(sc);
done:
if (error) {
if (opened) {
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Apr 26, 4:14 AM (18 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17797807
Default Alt Text
D47952.diff (4 KB)
Attached To
Mode
D47952: usb: serial: make more commands execute synchronously
Attached
Detach File
Event Timeline
Log In to Comment