summaryrefslogtreecommitdiffstats
path: root/sound/usb/midi.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2010-04-10 21:34:56 +0200
committerTakashi Iwai <tiwai@suse.de>2010-04-10 21:34:56 +0200
commit27762b2ce16d5c6f7bc8ab1aad1b9179076f997a (patch)
tree04108617a1ccc18e3cef39e780c67460da9d5a0d /sound/usb/midi.c
parent7b7b9042263f5cafb6ce85b3764375a8de7e22da (diff)
parent29aac005ff4dc8a5f50b80f4e5c4f59b21c0fb50 (diff)
downloadlinux-27762b2ce16d5c6f7bc8ab1aad1b9179076f997a.tar.bz2
Merge branch 'fix/misc' into topic/usb
Diffstat (limited to 'sound/usb/midi.c')
-rw-r--r--sound/usb/midi.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index c6ee4a18e513..2c1558c327bb 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -987,6 +987,8 @@ static void snd_usbmidi_output_drain(struct snd_rawmidi_substream *substream)
DEFINE_WAIT(wait);
long timeout = msecs_to_jiffies(50);
+ if (ep->umidi->disconnected)
+ return;
/*
* The substream buffer is empty, but some data might still be in the
* currently active URBs, so we have to wait for those to complete.
@@ -1124,14 +1126,21 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi* umidi,
* Frees an output endpoint.
* May be called when ep hasn't been initialized completely.
*/
-static void snd_usbmidi_out_endpoint_delete(struct snd_usb_midi_out_endpoint* ep)
+static void snd_usbmidi_out_endpoint_clear(struct snd_usb_midi_out_endpoint *ep)
{
unsigned int i;
for (i = 0; i < OUTPUT_URBS; ++i)
- if (ep->urbs[i].urb)
+ if (ep->urbs[i].urb) {
free_urb_and_buffer(ep->umidi, ep->urbs[i].urb,
ep->max_transfer);
+ ep->urbs[i].urb = NULL;
+ }
+}
+
+static void snd_usbmidi_out_endpoint_delete(struct snd_usb_midi_out_endpoint *ep)
+{
+ snd_usbmidi_out_endpoint_clear(ep);
kfree(ep);
}
@@ -1263,15 +1272,18 @@ void snd_usbmidi_disconnect(struct list_head* p)
usb_kill_urb(ep->out->urbs[j].urb);
if (umidi->usb_protocol_ops->finish_out_endpoint)
umidi->usb_protocol_ops->finish_out_endpoint(ep->out);
+ ep->out->active_urbs = 0;
+ if (ep->out->drain_urbs) {
+ ep->out->drain_urbs = 0;
+ wake_up(&ep->out->drain_wait);
+ }
}
if (ep->in)
for (j = 0; j < INPUT_URBS; ++j)
usb_kill_urb(ep->in->urbs[j]);
/* free endpoints here; later call can result in Oops */
- if (ep->out) {
- snd_usbmidi_out_endpoint_delete(ep->out);
- ep->out = NULL;
- }
+ if (ep->out)
+ snd_usbmidi_out_endpoint_clear(ep->out);
if (ep->in) {
snd_usbmidi_in_endpoint_delete(ep->in);
ep->in = NULL;