Page MenuHomeFreeBSD

D47952.diff
No OneTemporary

D47952.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
@@ -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

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)

Event Timeline