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