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 b2da478a0fae..c7cb207963f5 100644 --- a/sound/usb/usbmidi.c +++ b/sound/usb/usbmidi.c | |||
@@ -984,6 +984,8 @@ static void snd_usbmidi_output_drain(struct snd_rawmidi_substream *substream) | |||
984 | DEFINE_WAIT(wait); | 984 | DEFINE_WAIT(wait); |
985 | long timeout = msecs_to_jiffies(50); | 985 | long timeout = msecs_to_jiffies(50); |
986 | 986 | ||
987 | if (ep->umidi->disconnected) | ||
988 | return; | ||
987 | /* | 989 | /* |
988 | * The substream buffer is empty, but some data might still be in the | 990 | * The substream buffer is empty, but some data might still be in the |
989 | * currently active URBs, so we have to wait for those to complete. | 991 | * currently active URBs, so we have to wait for those to complete. |
@@ -1121,14 +1123,21 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi* umidi, | |||
1121 | * Frees an output endpoint. | 1123 | * Frees an output endpoint. |
1122 | * May be called when ep hasn't been initialized completely. | 1124 | * May be called when ep hasn't been initialized completely. |
1123 | */ | 1125 | */ |
1124 | static void snd_usbmidi_out_endpoint_delete(struct snd_usb_midi_out_endpoint* ep) | 1126 | static void snd_usbmidi_out_endpoint_clear(struct snd_usb_midi_out_endpoint *ep) |
1125 | { | 1127 | { |
1126 | unsigned int i; | 1128 | unsigned int i; |
1127 | 1129 | ||
1128 | for (i = 0; i < OUTPUT_URBS; ++i) | 1130 | for (i = 0; i < OUTPUT_URBS; ++i) |
1129 | if (ep->urbs[i].urb) | 1131 | if (ep->urbs[i].urb) { |
1130 | free_urb_and_buffer(ep->umidi, ep->urbs[i].urb, | 1132 | free_urb_and_buffer(ep->umidi, ep->urbs[i].urb, |
1131 | ep->max_transfer); | 1133 | ep->max_transfer); |
1134 | ep->urbs[i].urb = NULL; | ||
1135 | } | ||
1136 | } | ||
1137 | |||
1138 | static void snd_usbmidi_out_endpoint_delete(struct snd_usb_midi_out_endpoint *ep) | ||
1139 | { | ||
1140 | snd_usbmidi_out_endpoint_clear(ep); | ||
1132 | kfree(ep); | 1141 | kfree(ep); |
1133 | } | 1142 | } |
1134 | 1143 | ||
@@ -1260,15 +1269,18 @@ void snd_usbmidi_disconnect(struct list_head* p) | |||
1260 | usb_kill_urb(ep->out->urbs[j].urb); | 1269 | usb_kill_urb(ep->out->urbs[j].urb); |
1261 | if (umidi->usb_protocol_ops->finish_out_endpoint) | 1270 | if (umidi->usb_protocol_ops->finish_out_endpoint) |
1262 | umidi->usb_protocol_ops->finish_out_endpoint(ep->out); | 1271 | umidi->usb_protocol_ops->finish_out_endpoint(ep->out); |
1272 | ep->out->active_urbs = 0; | ||
1273 | if (ep->out->drain_urbs) { | ||
1274 | ep->out->drain_urbs = 0; | ||
1275 | wake_up(&ep->out->drain_wait); | ||
1276 | } | ||
1263 | } | 1277 | } |
1264 | if (ep->in) | 1278 | if (ep->in) |
1265 | for (j = 0; j < INPUT_URBS; ++j) | 1279 | for (j = 0; j < INPUT_URBS; ++j) |
1266 | usb_kill_urb(ep->in->urbs[j]); | 1280 | usb_kill_urb(ep->in->urbs[j]); |
1267 | /* free endpoints here; later call can result in Oops */ | 1281 | /* free endpoints here; later call can result in Oops */ |
1268 | if (ep->out) { | 1282 | if (ep->out) |
1269 | snd_usbmidi_out_endpoint_delete(ep->out); | 1283 | snd_usbmidi_out_endpoint_clear(ep->out); |
1270 | ep->out = NULL; | ||
1271 | } | ||
1272 | if (ep->in) { | 1284 | if (ep->in) { |
1273 | snd_usbmidi_in_endpoint_delete(ep->in); | 1285 | snd_usbmidi_in_endpoint_delete(ep->in); |
1274 | ep->in = NULL; | 1286 | ep->in = NULL; |