|
@@ -986,6 +986,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.
|
|
@@ -1123,14 +1125,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);
|
|
|
}
|
|
|
|
|
@@ -1262,15 +1271,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;
|