diff options
| -rw-r--r-- | sound/usb/usbmidi.c | 24 | 
1 files changed, 18 insertions, 6 deletions
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c index 2c59afd99611..9e28b20cb2ce 100644 --- a/sound/usb/usbmidi.c +++ b/sound/usb/usbmidi.c @@ -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;  | 
