Module Name: src
Committed By: mlelstv
Date: Sat May 14 10:52:29 UTC 2016
Modified Files:
src/sys/dev/usb: ucom.c
Log Message:
All com devices have an issue that they sleep in the final close
when they signal a hangup while still using the device. This allows
a concurrent open to succeed without proper locking because it
only checks the state of the tty layer.
This issue triggers an assertion in ucom due to a reused USB xfer,
but it can also cause misbehaviour in other com devices.
For now in ucom:
- make open block while close is in progress
- also serialize close operations
To generate a diff of this commit:
cvs rdiff -u -r1.112 -r1.113 src/sys/dev/usb/ucom.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/usb/ucom.c
diff -u src/sys/dev/usb/ucom.c:1.112 src/sys/dev/usb/ucom.c:1.113
--- src/sys/dev/usb/ucom.c:1.112 Tue May 10 10:40:33 2016
+++ src/sys/dev/usb/ucom.c Sat May 14 10:52:29 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: ucom.c,v 1.112 2016/05/10 10:40:33 skrll Exp $ */
+/* $NetBSD: ucom.c,v 1.113 2016/05/14 10:52:29 mlelstv Exp $ */
/*
* Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ucom.c,v 1.112 2016/05/10 10:40:33 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ucom.c,v 1.113 2016/05/14 10:52:29 mlelstv Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -174,6 +174,7 @@ struct ucom_softc {
int sc_swflags;
u_char sc_opening; /* lock during open */
+ u_char sc_closing; /* lock during close */
int sc_refcnt;
u_char sc_dying; /* disconnecting */
@@ -282,6 +283,7 @@ ucom_attach(device_t parent, device_t se
sc->sc_tx_stopped = 0;
sc->sc_swflags = 0;
sc->sc_opening = 0;
+ sc->sc_closing = 0;
sc->sc_refcnt = 0;
sc->sc_dying = 0;
@@ -542,9 +544,10 @@ ucomopen(dev_t dev, int flag, int mode,
}
/*
- * Do the following iff this is a first open.
+ * Wait while the device is initialized by the
+ * first opener or cleaned up by the last closer.
*/
- while (sc->sc_opening) {
+ while (sc->sc_opening || sc->sc_closing) {
error = cv_wait_sig(&sc->sc_opencv, &sc->sc_lock);
if (error) {
@@ -681,6 +684,10 @@ ucomclose(dev_t dev, int flag, int mode,
mutex_enter(&sc->sc_lock);
tp = sc->sc_tty;
+ while (sc->sc_closing)
+ cv_wait(&sc->sc_opencv, &sc->sc_lock);
+ sc->sc_closing = 1;
+
if (!ISSET(tp->t_state, TS_ISOPEN)) {
goto out;
}
@@ -706,6 +713,9 @@ ucomclose(dev_t dev, int flag, int mode,
usb_detach_broadcast(sc->sc_dev, &sc->sc_detachcv);
out:
+ sc->sc_closing = 0;
+ cv_signal(&sc->sc_opencv);
+
mutex_exit(&sc->sc_lock);
return 0;