--- x/sound/usb/midi.c +++ y/sound/usb/midi.c @@ -307,6 +307,8 @@ static void snd_usbmidi_do_output(struct for (;;) { if (!(ep->active_urbs & (1 << urb_index))) { urb = ep->urbs[urb_index].urb; + if (!urb) + goto next; urb->transfer_buffer_length = 0; ep->umidi->usb_protocol_ops->output(ep, urb); if (urb->transfer_buffer_length == 0) @@ -319,6 +321,7 @@ static void snd_usbmidi_do_output(struct break; ep->active_urbs |= 1 << urb_index; } + next: if (++urb_index >= OUTPUT_URBS) urb_index = 0; if (urb_index == ep->next_urb) @@ -1396,13 +1399,19 @@ static int snd_usbmidi_in_endpoint_creat static void snd_usbmidi_out_endpoint_clear(struct snd_usb_midi_out_endpoint *ep) { unsigned int i; + unsigned long flags; + spin_lock_irqsave(&ep->buffer_lock, flags); for (i = 0; i < OUTPUT_URBS; ++i) if (ep->urbs[i].urb) { - free_urb_and_buffer(ep->umidi, ep->urbs[i].urb, - ep->max_transfer); + struct urb *urb = ep->urbs[i].urb; + ep->urbs[i].urb = NULL; + spin_unlock_irqrestore(&ep->buffer_lock, flags); + free_urb_and_buffer(ep->umidi, urb, ep->max_transfer); + spin_lock_irqsave(&ep->buffer_lock, flags); } + spin_unlock_irqrestore(&ep->buffer_lock, flags); } static void snd_usbmidi_out_endpoint_delete(struct snd_usb_midi_out_endpoint *ep) @@ -1522,15 +1531,23 @@ static void snd_usbmidi_free(struct snd_ { int i; + timer_shutdown_sync(&umidi->error_timer); for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { struct snd_usb_midi_endpoint *ep = &umidi->endpoints[i]; - if (ep->out) + int j; + + if (ep->out) { + for (j = 0; j < OUTPUT_URBS; ++j) + usb_kill_urb(ep->out->urbs[j].urb); snd_usbmidi_out_endpoint_delete(ep->out); - if (ep->in) + } + if (ep->in) { + for (j = 0; j < INPUT_URBS; ++j) + usb_kill_urb(ep->in->urbs[j]); snd_usbmidi_in_endpoint_delete(ep->in); + } } mutex_destroy(&umidi->mutex); - timer_shutdown_sync(&umidi->error_timer); kfree(umidi); }