diff options
| -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 | } |
