Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/usb since we have to drop locks to call into the usb...



details:   https://anonhg.NetBSD.org/src/rev/b569e5a2668e
branches:  trunk
changeset: 773736:b569e5a2668e
user:      mrg <mrg%NetBSD.org@localhost>
date:      Tue Feb 14 19:28:22 2012 +0000

description:
since we have to drop locks to call into the usb code, we need to make
sure that only one caller ends up doing something in close_out_jack().
add a "closing" member that is set when closing and error out in various
places.

with this in place i can read and write from umidi without triggering
any locking or other obvious issues, though the writing is currently
broken (it worked in 5.99.60-era.)  it runs the correct time, but no
output occurs no the synth itself.  more work needed here.

diffstat:

 sys/dev/usb/umidi.c    |  38 ++++++++++++++++++++++++--------------
 sys/dev/usb/umidivar.h |   3 ++-
 2 files changed, 26 insertions(+), 15 deletions(-)

diffs (146 lines):

diff -r 221453c13df8 -r b569e5a2668e sys/dev/usb/umidi.c
--- a/sys/dev/usb/umidi.c       Tue Feb 14 18:57:35 2012 +0000
+++ b/sys/dev/usb/umidi.c       Tue Feb 14 19:28:22 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: umidi.c,v 1.58 2012/02/13 17:36:18 mrg Exp $   */
+/*     $NetBSD: umidi.c,v 1.59 2012/02/14 19:28:22 mrg Exp $   */
 /*
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: umidi.c,v 1.58 2012/02/13 17:36:18 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: umidi.c,v 1.59 2012/02/14 19:28:22 mrg Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -341,6 +341,7 @@
                return EIO;
 
        mididev->opened = 1;
+       mididev->closing = 0;
        mididev->flags = flags;
        if ((mididev->flags & FWRITE) && mididev->out_jack) {
                err = open_out_jack(mididev->out_jack, arg, ointr);
@@ -367,6 +368,8 @@
        struct umidi_mididev *mididev = addr;
 
        /* XXX SMP */
+       mididev->closing = 1;
+
        KERNEL_LOCK(1, curlwp);
        mutex_spin_exit(&mididev->sc->sc_lock);
 
@@ -374,11 +377,12 @@
                close_out_jack(mididev->out_jack);
        if ((mididev->flags & FREAD) && mididev->in_jack)
                close_in_jack(mididev->in_jack);
-       mididev->opened = 0;
 
        /* XXX SMP */
        mutex_spin_enter(&mididev->sc->sc_lock);
        KERNEL_UNLOCK_ONE(curlwp);
+
+       mididev->opened = 0;
 }
 
 int
@@ -387,7 +391,7 @@
 {
        struct umidi_mididev *mididev = addr;
 
-       if (!mididev->out_jack || !mididev->opened)
+       if (!mididev->out_jack || !mididev->opened || !mididev->closing)
                return EIO;
        
        return out_jack_output(mididev->out_jack, msg, len, (status>>4)&0xf);
@@ -399,7 +403,7 @@
        struct umidi_mididev *mididev = addr;
        int cin;
 
-       if (!mididev->out_jack || !mididev->opened)
+       if (!mididev->out_jack || !mididev->opened || !mididev->closing)
                return EIO;
 
        switch ( len ) {
@@ -418,7 +422,7 @@
        struct umidi_mididev *mididev = addr;
        int cin;
 
-       if (!mididev->out_jack || !mididev->opened)
+       if (!mididev->out_jack || !mididev->opened || !mididev->closing)
                return EIO;
 
        switch ( len ) {
@@ -437,7 +441,7 @@
        struct umidi_mididev *mididev = addr;
        u_char msg = d;
 
-       if (!mididev->out_jack || !mididev->opened)
+       if (!mididev->out_jack || !mididev->opened || !mididev->closing)
                return EIO;
 
        return out_jack_output(mididev->out_jack, &msg, 1, 0xf);
@@ -1154,11 +1158,10 @@
        u_int16_t mask;
        int err;
 
-
        if (jack->opened) {
                ep = jack->endpoint;
                sc = ep->sc;
-               KASSERT(mutex_owned(&sc->sc_lock));
+               mutex_spin_enter(&sc->sc_lock);
                mask = 1 << (jack->cable_number);
                while (mask & (ep->this_schedule | ep->next_schedule)) {
                        err = cv_timedwait_sig(&sc->sc_cv, &sc->sc_lock,
@@ -1166,10 +1169,17 @@
                        if (err)
                                break;
                }
-               jack->opened = 0;
-               jack->endpoint->num_open--;
-               ep->this_schedule &= ~mask;
-               ep->next_schedule &= ~mask;
+               /*
+                * We can re-enter this function from both close() and
+                * detach().  Make sure only one of them does this part.
+                */
+               if (jack->opened) {
+                       jack->opened = 0;
+                       jack->endpoint->num_open--;
+                       ep->this_schedule &= ~mask;
+                       ep->next_schedule &= ~mask;
+               }
+               mutex_spin_exit(&sc->sc_lock);
        }
 }
 
@@ -1179,7 +1189,7 @@
        if (jack->opened) {
                jack->opened = 0;
                if (--jack->endpoint->num_open == 0) {
-                   usbd_abort_pipe(jack->endpoint->pipe);
+                       usbd_abort_pipe(jack->endpoint->pipe);
                }
        }
 }
diff -r 221453c13df8 -r b569e5a2668e sys/dev/usb/umidivar.h
--- a/sys/dev/usb/umidivar.h    Tue Feb 14 18:57:35 2012 +0000
+++ b/sys/dev/usb/umidivar.h    Tue Feb 14 19:28:22 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: umidivar.h,v 1.17 2011/11/26 13:22:09 mrg Exp $        */
+/*     $NetBSD: umidivar.h,v 1.18 2012/02/14 19:28:23 mrg Exp $        */
 /*
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -51,6 +51,7 @@
        size_t                  label_len;
        /* */
        int                     opened;
+       int                     closing;
        int                     flags;
 };
 



Home | Main Index | Thread Index | Old Index