aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2009-07-13 07:40:36 -0400
committerTakashi Iwai <tiwai@suse.de>2009-07-15 05:56:19 -0400
commit4773d1fb8f37612336d2c929058bf96d3a1624b1 (patch)
treeffedcd72fc55f92fef039c7e2297b60ebe558d63
parent468b8fde24d49f5b34e9152981824b9d4ecd1a2e (diff)
sound: usb-audio: use multiple input URBs
Some newer USB MIDI interfaces use rather small packet sizes, so to get enough bandwidth, we have to be able to receive multiple packets in one USB frame, so we have to use multiple URBs. Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/usb/usbmidi.c87
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
66MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); 68MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
67MODULE_DESCRIPTION("USB Audio/MIDI helper module"); 69MODULE_DESCRIPTION("USB Audio/MIDI helper module");
@@ -143,7 +145,7 @@ struct snd_usb_midi_out_endpoint {
143 145
144struct snd_usb_midi_in_endpoint { 146struct 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)
306static void snd_usbmidi_error_timer(unsigned long data) 308static 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 */
923static void snd_usbmidi_in_endpoint_delete(struct snd_usb_midi_in_endpoint* ep) 927static 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)
1090void snd_usbmidi_disconnect(struct list_head* p) 1105void 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,
1692void snd_usbmidi_input_stop(struct list_head* p) 1708void 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
1705static void snd_usbmidi_input_start_ep(struct snd_usb_midi_in_endpoint* ep) 1722static 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 }