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;
};