Module Name:    src
Committed By:   mrg
Date:           Tue Feb 14 19:28:23 UTC 2012

Modified Files:
        src/sys/dev/usb: umidi.c umidivar.h

Log Message:
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.


To generate a diff of this commit:
cvs rdiff -u -r1.58 -r1.59 src/sys/dev/usb/umidi.c
cvs rdiff -u -r1.17 -r1.18 src/sys/dev/usb/umidivar.h

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/umidi.c
diff -u src/sys/dev/usb/umidi.c:1.58 src/sys/dev/usb/umidi.c:1.59
--- src/sys/dev/usb/umidi.c:1.58	Mon Feb 13 17:36:18 2012
+++ src/sys/dev/usb/umidi.c	Tue Feb 14 19:28:22 2012
@@ -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 @@ umidi_open(void *addr,
 		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 @@ umidi_close(void *addr)
 	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 @@ umidi_close(void *addr)
 		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 @@ umidi_channelmsg(void *addr, int status,
 {
 	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 @@ umidi_commonmsg(void *addr, int status, 
 	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 @@ umidi_sysex(void *addr, u_char *msg, int
 	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 @@ umidi_rtmsg(void *addr, int d)
 	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 @@ close_out_jack(struct umidi_jack *jack)
 	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 @@ close_out_jack(struct umidi_jack *jack)
 			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 @@ close_in_jack(struct umidi_jack *jack)
 	if (jack->opened) {
 		jack->opened = 0;
 		if (--jack->endpoint->num_open == 0) {
-		    usbd_abort_pipe(jack->endpoint->pipe);
+			usbd_abort_pipe(jack->endpoint->pipe);
 		}
 	}
 }

Index: src/sys/dev/usb/umidivar.h
diff -u src/sys/dev/usb/umidivar.h:1.17 src/sys/dev/usb/umidivar.h:1.18
--- src/sys/dev/usb/umidivar.h:1.17	Sat Nov 26 13:22:09 2011
+++ src/sys/dev/usb/umidivar.h	Tue Feb 14 19:28:23 2012
@@ -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 @@ struct umidi_mididev {
 	size_t			label_len;
 	/* */
 	int			opened;
+	int			closing;
 	int			flags;
 };
 

Reply via email to