diff options
Diffstat (limited to 'sound/usb/usbmidi.c')
-rw-r--r-- | sound/usb/usbmidi.c | 87 |
1 files changed, 54 insertions, 33 deletions
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c index 2fb35cc22a30..cc17401de95e 100644 --- a/sound/usb/usbmidi.c +++ b/sound/usb/usbmidi.c | |||
@@ -62,6 +62,8 @@ | |||
62 | */ | 62 | */ |
63 | #define ERROR_DELAY_JIFFIES (HZ / 10) | 63 | #define ERROR_DELAY_JIFFIES (HZ / 10) |
64 | 64 | ||
65 | #define INPUT_URBS 7 | ||
66 | |||
65 | 67 | ||
66 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); | 68 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); |
67 | MODULE_DESCRIPTION("USB Audio/MIDI helper module"); | 69 | MODULE_DESCRIPTION("USB Audio/MIDI helper module"); |
@@ -143,7 +145,7 @@ struct snd_usb_midi_out_endpoint { | |||
143 | 145 | ||
144 | struct snd_usb_midi_in_endpoint { | 146 | struct snd_usb_midi_in_endpoint { |
145 | struct snd_usb_midi* umidi; | 147 | struct snd_usb_midi* umidi; |
146 | struct urb* urb; | 148 | struct urb* urbs[INPUT_URBS]; |
147 | struct usbmidi_in_port { | 149 | struct usbmidi_in_port { |
148 | struct snd_rawmidi_substream *substream; | 150 | struct snd_rawmidi_substream *substream; |
149 | u8 running_status_length; | 151 | u8 running_status_length; |
@@ -306,7 +308,7 @@ static void snd_usbmidi_out_tasklet(unsigned long data) | |||
306 | static void snd_usbmidi_error_timer(unsigned long data) | 308 | static void snd_usbmidi_error_timer(unsigned long data) |
307 | { | 309 | { |
308 | struct snd_usb_midi *umidi = (struct snd_usb_midi *)data; | 310 | struct snd_usb_midi *umidi = (struct snd_usb_midi *)data; |
309 | int i; | 311 | unsigned int i, j; |
310 | 312 | ||
311 | spin_lock(&umidi->disc_lock); | 313 | spin_lock(&umidi->disc_lock); |
312 | if (umidi->disconnected) { | 314 | if (umidi->disconnected) { |
@@ -317,8 +319,10 @@ static void snd_usbmidi_error_timer(unsigned long data) | |||
317 | struct snd_usb_midi_in_endpoint *in = umidi->endpoints[i].in; | 319 | struct snd_usb_midi_in_endpoint *in = umidi->endpoints[i].in; |
318 | if (in && in->error_resubmit) { | 320 | if (in && in->error_resubmit) { |
319 | in->error_resubmit = 0; | 321 | in->error_resubmit = 0; |
320 | in->urb->dev = umidi->chip->dev; | 322 | for (j = 0; j < INPUT_URBS; ++j) { |
321 | snd_usbmidi_submit_urb(in->urb, GFP_ATOMIC); | 323 | in->urbs[j]->dev = umidi->chip->dev; |
324 | snd_usbmidi_submit_urb(in->urbs[j], GFP_ATOMIC); | ||
325 | } | ||
322 | } | 326 | } |
323 | if (umidi->endpoints[i].out) | 327 | if (umidi->endpoints[i].out) |
324 | snd_usbmidi_do_output(umidi->endpoints[i].out); | 328 | snd_usbmidi_do_output(umidi->endpoints[i].out); |
@@ -922,12 +926,16 @@ static struct snd_rawmidi_ops snd_usbmidi_input_ops = { | |||
922 | */ | 926 | */ |
923 | static void snd_usbmidi_in_endpoint_delete(struct snd_usb_midi_in_endpoint* ep) | 927 | static void snd_usbmidi_in_endpoint_delete(struct snd_usb_midi_in_endpoint* ep) |
924 | { | 928 | { |
925 | if (ep->urb) { | 929 | unsigned int i; |
926 | usb_buffer_free(ep->umidi->chip->dev, | 930 | |
927 | ep->urb->transfer_buffer_length, | 931 | for (i = 0; i < INPUT_URBS; ++i) { |
928 | ep->urb->transfer_buffer, | 932 | if (ep->urbs[i]) { |
929 | ep->urb->transfer_dma); | 933 | usb_buffer_free(ep->umidi->chip->dev, |
930 | usb_free_urb(ep->urb); | 934 | ep->urbs[i]->transfer_buffer_length, |
935 | ep->urbs[i]->transfer_buffer, | ||
936 | ep->urbs[i]->transfer_dma); | ||
937 | usb_free_urb(ep->urbs[i]); | ||
938 | } | ||
931 | } | 939 | } |
932 | kfree(ep); | 940 | kfree(ep); |
933 | } | 941 | } |
@@ -943,6 +951,7 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi* umidi, | |||
943 | void* buffer; | 951 | void* buffer; |
944 | unsigned int pipe; | 952 | unsigned int pipe; |
945 | int length; | 953 | int length; |
954 | unsigned int i; | ||
946 | 955 | ||
947 | rep->in = NULL; | 956 | rep->in = NULL; |
948 | ep = kzalloc(sizeof(*ep), GFP_KERNEL); | 957 | ep = kzalloc(sizeof(*ep), GFP_KERNEL); |
@@ -950,30 +959,36 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi* umidi, | |||
950 | return -ENOMEM; | 959 | return -ENOMEM; |
951 | ep->umidi = umidi; | 960 | ep->umidi = umidi; |
952 | 961 | ||
953 | ep->urb = usb_alloc_urb(0, GFP_KERNEL); | 962 | for (i = 0; i < INPUT_URBS; ++i) { |
954 | if (!ep->urb) { | 963 | ep->urbs[i] = usb_alloc_urb(0, GFP_KERNEL); |
955 | snd_usbmidi_in_endpoint_delete(ep); | 964 | if (!ep->urbs[i]) { |
956 | return -ENOMEM; | 965 | snd_usbmidi_in_endpoint_delete(ep); |
966 | return -ENOMEM; | ||
967 | } | ||
957 | } | 968 | } |
958 | if (ep_info->in_interval) | 969 | if (ep_info->in_interval) |
959 | pipe = usb_rcvintpipe(umidi->chip->dev, ep_info->in_ep); | 970 | pipe = usb_rcvintpipe(umidi->chip->dev, ep_info->in_ep); |
960 | else | 971 | else |
961 | pipe = usb_rcvbulkpipe(umidi->chip->dev, ep_info->in_ep); | 972 | pipe = usb_rcvbulkpipe(umidi->chip->dev, ep_info->in_ep); |
962 | length = usb_maxpacket(umidi->chip->dev, pipe, 0); | 973 | length = usb_maxpacket(umidi->chip->dev, pipe, 0); |
963 | buffer = usb_buffer_alloc(umidi->chip->dev, length, GFP_KERNEL, | 974 | for (i = 0; i < INPUT_URBS; ++i) { |
964 | &ep->urb->transfer_dma); | 975 | buffer = usb_buffer_alloc(umidi->chip->dev, length, GFP_KERNEL, |
965 | if (!buffer) { | 976 | &ep->urbs[i]->transfer_dma); |
966 | snd_usbmidi_in_endpoint_delete(ep); | 977 | if (!buffer) { |
967 | return -ENOMEM; | 978 | snd_usbmidi_in_endpoint_delete(ep); |
979 | return -ENOMEM; | ||
980 | } | ||
981 | if (ep_info->in_interval) | ||
982 | usb_fill_int_urb(ep->urbs[i], umidi->chip->dev, | ||
983 | pipe, buffer, length, | ||
984 | snd_usbmidi_in_urb_complete, | ||
985 | ep, ep_info->in_interval); | ||
986 | else | ||
987 | usb_fill_bulk_urb(ep->urbs[i], umidi->chip->dev, | ||
988 | pipe, buffer, length, | ||
989 | snd_usbmidi_in_urb_complete, ep); | ||
990 | ep->urbs[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP; | ||
968 | } | 991 | } |
969 | if (ep_info->in_interval) | ||
970 | usb_fill_int_urb(ep->urb, umidi->chip->dev, pipe, buffer, | ||
971 | length, snd_usbmidi_in_urb_complete, ep, | ||
972 | ep_info->in_interval); | ||
973 | else | ||
974 | usb_fill_bulk_urb(ep->urb, umidi->chip->dev, pipe, buffer, | ||
975 | length, snd_usbmidi_in_urb_complete, ep); | ||
976 | ep->urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; | ||
977 | 992 | ||
978 | rep->in = ep; | 993 | rep->in = ep; |
979 | return 0; | 994 | return 0; |
@@ -1090,7 +1105,7 @@ static void snd_usbmidi_free(struct snd_usb_midi* umidi) | |||
1090 | void snd_usbmidi_disconnect(struct list_head* p) | 1105 | void snd_usbmidi_disconnect(struct list_head* p) |
1091 | { | 1106 | { |
1092 | struct snd_usb_midi* umidi; | 1107 | struct snd_usb_midi* umidi; |
1093 | int i; | 1108 | unsigned int i, j; |
1094 | 1109 | ||
1095 | umidi = list_entry(p, struct snd_usb_midi, list); | 1110 | umidi = list_entry(p, struct snd_usb_midi, list); |
1096 | /* | 1111 | /* |
@@ -1111,7 +1126,8 @@ void snd_usbmidi_disconnect(struct list_head* p) | |||
1111 | umidi->usb_protocol_ops->finish_out_endpoint(ep->out); | 1126 | umidi->usb_protocol_ops->finish_out_endpoint(ep->out); |
1112 | } | 1127 | } |
1113 | if (ep->in) | 1128 | if (ep->in) |
1114 | usb_kill_urb(ep->in->urb); | 1129 | for (j = 0; j < INPUT_URBS; ++j) |
1130 | usb_kill_urb(ep->in->urbs[j]); | ||
1115 | /* free endpoints here; later call can result in Oops */ | 1131 | /* free endpoints here; later call can result in Oops */ |
1116 | if (ep->out) { | 1132 | if (ep->out) { |
1117 | snd_usbmidi_out_endpoint_delete(ep->out); | 1133 | snd_usbmidi_out_endpoint_delete(ep->out); |
@@ -1692,20 +1708,25 @@ static int snd_usbmidi_create_rawmidi(struct snd_usb_midi* umidi, | |||
1692 | void snd_usbmidi_input_stop(struct list_head* p) | 1708 | void snd_usbmidi_input_stop(struct list_head* p) |
1693 | { | 1709 | { |
1694 | struct snd_usb_midi* umidi; | 1710 | struct snd_usb_midi* umidi; |
1695 | int i; | 1711 | unsigned int i, j; |
1696 | 1712 | ||
1697 | umidi = list_entry(p, struct snd_usb_midi, list); | 1713 | umidi = list_entry(p, struct snd_usb_midi, list); |
1698 | for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { | 1714 | for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { |
1699 | struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i]; | 1715 | struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i]; |
1700 | if (ep->in) | 1716 | if (ep->in) |
1701 | usb_kill_urb(ep->in->urb); | 1717 | for (j = 0; j < INPUT_URBS; ++j) |
1718 | usb_kill_urb(ep->in->urbs[j]); | ||
1702 | } | 1719 | } |
1703 | } | 1720 | } |
1704 | 1721 | ||
1705 | static void snd_usbmidi_input_start_ep(struct snd_usb_midi_in_endpoint* ep) | 1722 | static void snd_usbmidi_input_start_ep(struct snd_usb_midi_in_endpoint* ep) |
1706 | { | 1723 | { |
1707 | if (ep) { | 1724 | unsigned int i; |
1708 | struct urb* urb = ep->urb; | 1725 | |
1726 | if (!ep) | ||
1727 | return; | ||
1728 | for (i = 0; i < INPUT_URBS; ++i) { | ||
1729 | struct urb* urb = ep->urbs[i]; | ||
1709 | urb->dev = ep->umidi->chip->dev; | 1730 | urb->dev = ep->umidi->chip->dev; |
1710 | snd_usbmidi_submit_urb(urb, GFP_KERNEL); | 1731 | snd_usbmidi_submit_urb(urb, GFP_KERNEL); |
1711 | } | 1732 | } |