diff options
Diffstat (limited to 'sound/usb/usbaudio.c')
-rw-r--r-- | sound/usb/usbaudio.c | 52 |
1 files changed, 33 insertions, 19 deletions
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 8d4a085f642a..13ff66b0a532 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c | |||
@@ -127,6 +127,7 @@ struct audioformat { | |||
127 | 127 | ||
128 | struct snd_urb_ctx { | 128 | struct snd_urb_ctx { |
129 | struct urb *urb; | 129 | struct urb *urb; |
130 | unsigned int buffer_size; /* size of data buffer, if data URB */ | ||
130 | snd_usb_substream_t *subs; | 131 | snd_usb_substream_t *subs; |
131 | int index; /* index for urb array */ | 132 | int index; /* index for urb array */ |
132 | int packets; /* number of packets per urb */ | 133 | int packets; /* number of packets per urb */ |
@@ -176,7 +177,8 @@ struct snd_usb_substream { | |||
176 | unsigned int nurbs; /* # urbs */ | 177 | unsigned int nurbs; /* # urbs */ |
177 | snd_urb_ctx_t dataurb[MAX_URBS]; /* data urb table */ | 178 | snd_urb_ctx_t dataurb[MAX_URBS]; /* data urb table */ |
178 | snd_urb_ctx_t syncurb[SYNC_URBS]; /* sync urb table */ | 179 | snd_urb_ctx_t syncurb[SYNC_URBS]; /* sync urb table */ |
179 | char syncbuf[SYNC_URBS * 4]; /* sync buffer; it's so small - let's get static */ | 180 | char *syncbuf; /* sync buffer for all sync URBs */ |
181 | dma_addr_t sync_dma; /* DMA address of syncbuf */ | ||
180 | 182 | ||
181 | u64 formats; /* format bitmasks (all or'ed) */ | 183 | u64 formats; /* format bitmasks (all or'ed) */ |
182 | unsigned int num_formats; /* number of supported audio formats (list) */ | 184 | unsigned int num_formats; /* number of supported audio formats (list) */ |
@@ -855,7 +857,10 @@ static int snd_usb_pcm_trigger(snd_pcm_substream_t *substream, int cmd) | |||
855 | static void release_urb_ctx(snd_urb_ctx_t *u) | 857 | static void release_urb_ctx(snd_urb_ctx_t *u) |
856 | { | 858 | { |
857 | if (u->urb) { | 859 | if (u->urb) { |
858 | kfree(u->urb->transfer_buffer); | 860 | if (u->buffer_size) |
861 | usb_buffer_free(u->subs->dev, u->buffer_size, | ||
862 | u->urb->transfer_buffer, | ||
863 | u->urb->transfer_dma); | ||
859 | usb_free_urb(u->urb); | 864 | usb_free_urb(u->urb); |
860 | u->urb = NULL; | 865 | u->urb = NULL; |
861 | } | 866 | } |
@@ -876,6 +881,9 @@ static void release_substream_urbs(snd_usb_substream_t *subs, int force) | |||
876 | release_urb_ctx(&subs->dataurb[i]); | 881 | release_urb_ctx(&subs->dataurb[i]); |
877 | for (i = 0; i < SYNC_URBS; i++) | 882 | for (i = 0; i < SYNC_URBS; i++) |
878 | release_urb_ctx(&subs->syncurb[i]); | 883 | release_urb_ctx(&subs->syncurb[i]); |
884 | usb_buffer_free(subs->dev, SYNC_URBS * 4, | ||
885 | subs->syncbuf, subs->sync_dma); | ||
886 | subs->syncbuf = NULL; | ||
879 | subs->nurbs = 0; | 887 | subs->nurbs = 0; |
880 | } | 888 | } |
881 | 889 | ||
@@ -986,21 +994,19 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by | |||
986 | u->index = i; | 994 | u->index = i; |
987 | u->subs = subs; | 995 | u->subs = subs; |
988 | u->packets = npacks[i]; | 996 | u->packets = npacks[i]; |
997 | u->buffer_size = maxsize * u->packets; | ||
989 | if (subs->fmt_type == USB_FORMAT_TYPE_II) | 998 | if (subs->fmt_type == USB_FORMAT_TYPE_II) |
990 | u->packets++; /* for transfer delimiter */ | 999 | u->packets++; /* for transfer delimiter */ |
991 | u->urb = usb_alloc_urb(u->packets, GFP_KERNEL); | 1000 | u->urb = usb_alloc_urb(u->packets, GFP_KERNEL); |
992 | if (! u->urb) { | 1001 | if (! u->urb) |
993 | release_substream_urbs(subs, 0); | 1002 | goto out_of_memory; |
994 | return -ENOMEM; | 1003 | u->urb->transfer_buffer = |
995 | } | 1004 | usb_buffer_alloc(subs->dev, u->buffer_size, GFP_KERNEL, |
996 | u->urb->transfer_buffer = kmalloc(maxsize * u->packets, | 1005 | &u->urb->transfer_dma); |
997 | GFP_KERNEL); | 1006 | if (! u->urb->transfer_buffer) |
998 | if (! u->urb->transfer_buffer) { | 1007 | goto out_of_memory; |
999 | release_substream_urbs(subs, 0); | ||
1000 | return -ENOMEM; | ||
1001 | } | ||
1002 | u->urb->pipe = subs->datapipe; | 1008 | u->urb->pipe = subs->datapipe; |
1003 | u->urb->transfer_flags = URB_ISO_ASAP; | 1009 | u->urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; |
1004 | u->urb->interval = 1 << subs->datainterval; | 1010 | u->urb->interval = 1 << subs->datainterval; |
1005 | u->urb->context = u; | 1011 | u->urb->context = u; |
1006 | u->urb->complete = snd_usb_complete_callback(snd_complete_urb); | 1012 | u->urb->complete = snd_usb_complete_callback(snd_complete_urb); |
@@ -1008,20 +1014,24 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by | |||
1008 | 1014 | ||
1009 | if (subs->syncpipe) { | 1015 | if (subs->syncpipe) { |
1010 | /* allocate and initialize sync urbs */ | 1016 | /* allocate and initialize sync urbs */ |
1017 | subs->syncbuf = usb_buffer_alloc(subs->dev, SYNC_URBS * 4, | ||
1018 | GFP_KERNEL, &subs->sync_dma); | ||
1019 | if (! subs->syncbuf) | ||
1020 | goto out_of_memory; | ||
1011 | for (i = 0; i < SYNC_URBS; i++) { | 1021 | for (i = 0; i < SYNC_URBS; i++) { |
1012 | snd_urb_ctx_t *u = &subs->syncurb[i]; | 1022 | snd_urb_ctx_t *u = &subs->syncurb[i]; |
1013 | u->index = i; | 1023 | u->index = i; |
1014 | u->subs = subs; | 1024 | u->subs = subs; |
1015 | u->packets = 1; | 1025 | u->packets = 1; |
1016 | u->urb = usb_alloc_urb(1, GFP_KERNEL); | 1026 | u->urb = usb_alloc_urb(1, GFP_KERNEL); |
1017 | if (! u->urb) { | 1027 | if (! u->urb) |
1018 | release_substream_urbs(subs, 0); | 1028 | goto out_of_memory; |
1019 | return -ENOMEM; | ||
1020 | } | ||
1021 | u->urb->transfer_buffer = subs->syncbuf + i * 4; | 1029 | u->urb->transfer_buffer = subs->syncbuf + i * 4; |
1030 | u->urb->transfer_dma = subs->sync_dma + i * 4; | ||
1022 | u->urb->transfer_buffer_length = 4; | 1031 | u->urb->transfer_buffer_length = 4; |
1023 | u->urb->pipe = subs->syncpipe; | 1032 | u->urb->pipe = subs->syncpipe; |
1024 | u->urb->transfer_flags = URB_ISO_ASAP; | 1033 | u->urb->transfer_flags = URB_ISO_ASAP | |
1034 | URB_NO_TRANSFER_DMA_MAP; | ||
1025 | u->urb->number_of_packets = 1; | 1035 | u->urb->number_of_packets = 1; |
1026 | u->urb->interval = 1 << subs->syncinterval; | 1036 | u->urb->interval = 1 << subs->syncinterval; |
1027 | u->urb->context = u; | 1037 | u->urb->context = u; |
@@ -1029,6 +1039,10 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by | |||
1029 | } | 1039 | } |
1030 | } | 1040 | } |
1031 | return 0; | 1041 | return 0; |
1042 | |||
1043 | out_of_memory: | ||
1044 | release_substream_urbs(subs, 0); | ||
1045 | return -ENOMEM; | ||
1032 | } | 1046 | } |
1033 | 1047 | ||
1034 | 1048 | ||
@@ -2036,7 +2050,7 @@ static void init_substream(snd_usb_stream_t *as, int stream, struct audioformat | |||
2036 | subs->ops = audio_urb_ops_high_speed[stream]; | 2050 | subs->ops = audio_urb_ops_high_speed[stream]; |
2037 | snd_pcm_lib_preallocate_pages(as->pcm->streams[stream].substream, | 2051 | snd_pcm_lib_preallocate_pages(as->pcm->streams[stream].substream, |
2038 | SNDRV_DMA_TYPE_CONTINUOUS, | 2052 | SNDRV_DMA_TYPE_CONTINUOUS, |
2039 | snd_dma_continuous_data(GFP_KERNEL), | 2053 | snd_dma_continuous_data(GFP_NOIO), |
2040 | 64 * 1024, 128 * 1024); | 2054 | 64 * 1024, 128 * 1024); |
2041 | snd_pcm_set_ops(as->pcm, stream, | 2055 | snd_pcm_set_ops(as->pcm, stream, |
2042 | stream == SNDRV_PCM_STREAM_PLAYBACK ? | 2056 | stream == SNDRV_PCM_STREAM_PLAYBACK ? |