Skip to content

Commit

Permalink
[ALSA] usb-audio: use usb_buffer_alloc/free
Browse files Browse the repository at this point in the history
USB generic driver
Use the USB buffer allocation functions to avoid repeated DMA mappings
of our buffers, which are re-used quite a lot.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
  • Loading branch information
Clemens Ladisch authored and Jaroslav Kysela committed Aug 30, 2005
1 parent daa150e commit 55851f7
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 23 deletions.
52 changes: 33 additions & 19 deletions sound/usb/usbaudio.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ struct audioformat {

struct snd_urb_ctx {
struct urb *urb;
unsigned int buffer_size; /* size of data buffer, if data URB */
snd_usb_substream_t *subs;
int index; /* index for urb array */
int packets; /* number of packets per urb */
Expand Down Expand Up @@ -176,7 +177,8 @@ struct snd_usb_substream {
unsigned int nurbs; /* # urbs */
snd_urb_ctx_t dataurb[MAX_URBS]; /* data urb table */
snd_urb_ctx_t syncurb[SYNC_URBS]; /* sync urb table */
char syncbuf[SYNC_URBS * 4]; /* sync buffer; it's so small - let's get static */
char *syncbuf; /* sync buffer for all sync URBs */
dma_addr_t sync_dma; /* DMA address of syncbuf */

u64 formats; /* format bitmasks (all or'ed) */
unsigned int num_formats; /* number of supported audio formats (list) */
Expand Down Expand Up @@ -855,7 +857,10 @@ static int snd_usb_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
static void release_urb_ctx(snd_urb_ctx_t *u)
{
if (u->urb) {
kfree(u->urb->transfer_buffer);
if (u->buffer_size)
usb_buffer_free(u->subs->dev, u->buffer_size,
u->urb->transfer_buffer,
u->urb->transfer_dma);
usb_free_urb(u->urb);
u->urb = NULL;
}
Expand All @@ -876,6 +881,9 @@ static void release_substream_urbs(snd_usb_substream_t *subs, int force)
release_urb_ctx(&subs->dataurb[i]);
for (i = 0; i < SYNC_URBS; i++)
release_urb_ctx(&subs->syncurb[i]);
usb_buffer_free(subs->dev, SYNC_URBS * 4,
subs->syncbuf, subs->sync_dma);
subs->syncbuf = NULL;
subs->nurbs = 0;
}

Expand Down Expand Up @@ -986,49 +994,55 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by
u->index = i;
u->subs = subs;
u->packets = npacks[i];
u->buffer_size = maxsize * u->packets;
if (subs->fmt_type == USB_FORMAT_TYPE_II)
u->packets++; /* for transfer delimiter */
u->urb = usb_alloc_urb(u->packets, GFP_KERNEL);
if (! u->urb) {
release_substream_urbs(subs, 0);
return -ENOMEM;
}
u->urb->transfer_buffer = kmalloc(maxsize * u->packets,
GFP_KERNEL);
if (! u->urb->transfer_buffer) {
release_substream_urbs(subs, 0);
return -ENOMEM;
}
if (! u->urb)
goto out_of_memory;
u->urb->transfer_buffer =
usb_buffer_alloc(subs->dev, u->buffer_size, GFP_KERNEL,
&u->urb->transfer_dma);
if (! u->urb->transfer_buffer)
goto out_of_memory;
u->urb->pipe = subs->datapipe;
u->urb->transfer_flags = URB_ISO_ASAP;
u->urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
u->urb->interval = 1 << subs->datainterval;
u->urb->context = u;
u->urb->complete = snd_usb_complete_callback(snd_complete_urb);
}

if (subs->syncpipe) {
/* allocate and initialize sync urbs */
subs->syncbuf = usb_buffer_alloc(subs->dev, SYNC_URBS * 4,
GFP_KERNEL, &subs->sync_dma);
if (! subs->syncbuf)
goto out_of_memory;
for (i = 0; i < SYNC_URBS; i++) {
snd_urb_ctx_t *u = &subs->syncurb[i];
u->index = i;
u->subs = subs;
u->packets = 1;
u->urb = usb_alloc_urb(1, GFP_KERNEL);
if (! u->urb) {
release_substream_urbs(subs, 0);
return -ENOMEM;
}
if (! u->urb)
goto out_of_memory;
u->urb->transfer_buffer = subs->syncbuf + i * 4;
u->urb->transfer_dma = subs->sync_dma + i * 4;
u->urb->transfer_buffer_length = 4;
u->urb->pipe = subs->syncpipe;
u->urb->transfer_flags = URB_ISO_ASAP;
u->urb->transfer_flags = URB_ISO_ASAP |
URB_NO_TRANSFER_DMA_MAP;
u->urb->number_of_packets = 1;
u->urb->interval = 1 << subs->syncinterval;
u->urb->context = u;
u->urb->complete = snd_usb_complete_callback(snd_complete_sync_urb);
}
}
return 0;

out_of_memory:
release_substream_urbs(subs, 0);
return -ENOMEM;
}


Expand Down Expand Up @@ -2036,7 +2050,7 @@ static void init_substream(snd_usb_stream_t *as, int stream, struct audioformat
subs->ops = audio_urb_ops_high_speed[stream];
snd_pcm_lib_preallocate_pages(as->pcm->streams[stream].substream,
SNDRV_DMA_TYPE_CONTINUOUS,
snd_dma_continuous_data(GFP_KERNEL),
snd_dma_continuous_data(GFP_NOIO),
64 * 1024, 128 * 1024);
snd_pcm_set_ops(as->pcm, stream,
stream == SNDRV_PCM_STREAM_PLAYBACK ?
Expand Down
17 changes: 13 additions & 4 deletions sound/usb/usbmidi.c
Original file line number Diff line number Diff line change
Expand Up @@ -765,7 +765,10 @@ static snd_rawmidi_ops_t snd_usbmidi_input_ops = {
static void snd_usbmidi_in_endpoint_delete(snd_usb_midi_in_endpoint_t* ep)
{
if (ep->urb) {
kfree(ep->urb->transfer_buffer);
usb_buffer_free(ep->umidi->chip->dev,
ep->urb->transfer_buffer_length,
ep->urb->transfer_buffer,
ep->urb->transfer_dma);
usb_free_urb(ep->urb);
}
kfree(ep);
Expand Down Expand Up @@ -799,7 +802,8 @@ static int snd_usbmidi_in_endpoint_create(snd_usb_midi_t* umidi,
else
pipe = usb_rcvbulkpipe(umidi->chip->dev, ep_info->in_ep);
length = usb_maxpacket(umidi->chip->dev, pipe, 0);
buffer = kmalloc(length, GFP_KERNEL);
buffer = usb_buffer_alloc(umidi->chip->dev, length, GFP_KERNEL,
&ep->urb->transfer_dma);
if (!buffer) {
snd_usbmidi_in_endpoint_delete(ep);
return -ENOMEM;
Expand All @@ -812,6 +816,7 @@ static int snd_usbmidi_in_endpoint_create(snd_usb_midi_t* umidi,
usb_fill_bulk_urb(ep->urb, umidi->chip->dev, pipe, buffer, length,
snd_usb_complete_callback(snd_usbmidi_in_urb_complete),
ep);
ep->urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;

rep->in = ep;
return 0;
Expand All @@ -835,7 +840,9 @@ static void snd_usbmidi_out_endpoint_delete(snd_usb_midi_out_endpoint_t* ep)
if (ep->tasklet.func)
tasklet_kill(&ep->tasklet);
if (ep->urb) {
kfree(ep->urb->transfer_buffer);
usb_buffer_free(ep->umidi->chip->dev, ep->max_transfer,
ep->urb->transfer_buffer,
ep->urb->transfer_dma);
usb_free_urb(ep->urb);
}
kfree(ep);
Expand Down Expand Up @@ -867,14 +874,16 @@ static int snd_usbmidi_out_endpoint_create(snd_usb_midi_t* umidi,
/* we never use interrupt output pipes */
pipe = usb_sndbulkpipe(umidi->chip->dev, ep_info->out_ep);
ep->max_transfer = usb_maxpacket(umidi->chip->dev, pipe, 1);
buffer = kmalloc(ep->max_transfer, GFP_KERNEL);
buffer = usb_buffer_alloc(umidi->chip->dev, ep->max_transfer,
GFP_KERNEL, &ep->urb->transfer_dma);
if (!buffer) {
snd_usbmidi_out_endpoint_delete(ep);
return -ENOMEM;
}
usb_fill_bulk_urb(ep->urb, umidi->chip->dev, pipe, buffer,
ep->max_transfer,
snd_usb_complete_callback(snd_usbmidi_out_urb_complete), ep);
ep->urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;

spin_lock_init(&ep->buffer_lock);
tasklet_init(&ep->tasklet, snd_usbmidi_out_tasklet, (unsigned long)ep);
Expand Down

0 comments on commit 55851f7

Please sign in to comment.