Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/usb All com devices have an issue that they sleep in...



details:   https://anonhg.NetBSD.org/src/rev/5916a73eca99
branches:  trunk
changeset: 345245:5916a73eca99
user:      mlelstv <mlelstv%NetBSD.org@localhost>
date:      Sat May 14 10:52:29 2016 +0000

description:
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

diffstat:

 sys/dev/usb/ucom.c |  18 ++++++++++++++----
 1 files changed, 14 insertions(+), 4 deletions(-)

diffs (68 lines):

diff -r 6cd8e0472e49 -r 5916a73eca99 sys/dev/usb/ucom.c
--- a/sys/dev/usb/ucom.c        Sat May 14 10:07:52 2016 +0000
+++ b/sys/dev/usb/ucom.c        Sat May 14 10:52:29 2016 +0000
@@ -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 @@
        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 @@
        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 @@
        }
 
        /*
-        * 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 @@
        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 @@
                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;



Home | Main Index | Thread Index | Old Index