Commit b263a9bd authored by Clemens Ladisch's avatar Clemens Ladisch Committed by Jaroslav Kysela

[ALSA] usb-audio: optimize handling of capture URBs

USB generic driver
When preparing capture URBs, we don't need to stop when we cross a
period boundary because we now never handle more than one millisecond of
data per URB anyway.

When handling captured data, use an extra flag to call
snd_pcm_period_elapsed() no more than once.  This allows us to move the
period boundary checking code before the copying of the data which
avoids a second locking of the substream's lock.
Signed-off-by: default avatarClemens Ladisch <clemens@ladisch.de>
parent 99250872
...@@ -311,27 +311,18 @@ static int prepare_capture_urb(snd_usb_substream_t *subs, ...@@ -311,27 +311,18 @@ static int prepare_capture_urb(snd_usb_substream_t *subs,
struct urb *urb) struct urb *urb)
{ {
int i, offs; int i, offs;
unsigned long flags;
snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context; snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
offs = 0; offs = 0;
urb->dev = ctx->subs->dev; /* we need to set this at each time */ urb->dev = ctx->subs->dev; /* we need to set this at each time */
urb->number_of_packets = 0;
spin_lock_irqsave(&subs->lock, flags);
for (i = 0; i < ctx->packets; i++) { for (i = 0; i < ctx->packets; i++) {
urb->iso_frame_desc[i].offset = offs; urb->iso_frame_desc[i].offset = offs;
urb->iso_frame_desc[i].length = subs->curpacksize; urb->iso_frame_desc[i].length = subs->curpacksize;
offs += subs->curpacksize; offs += subs->curpacksize;
urb->number_of_packets++;
subs->transfer_sched += subs->curframesize;
if (subs->transfer_sched >= runtime->period_size) {
subs->transfer_sched -= runtime->period_size;
break;
}
} }
spin_unlock_irqrestore(&subs->lock, flags);
urb->transfer_buffer = ctx->buf; urb->transfer_buffer = ctx->buf;
urb->transfer_buffer_length = offs; urb->transfer_buffer_length = offs;
urb->number_of_packets = ctx->packets;
#if 0 // for check #if 0 // for check
if (! urb->bandwidth) { if (! urb->bandwidth) {
int bustime; int bustime;
...@@ -359,6 +350,7 @@ static int retire_capture_urb(snd_usb_substream_t *subs, ...@@ -359,6 +350,7 @@ static int retire_capture_urb(snd_usb_substream_t *subs,
unsigned char *cp; unsigned char *cp;
int i; int i;
unsigned int stride, len, oldptr; unsigned int stride, len, oldptr;
int period_elapsed = 0;
stride = runtime->frame_bits >> 3; stride = runtime->frame_bits >> 3;
...@@ -378,6 +370,10 @@ static int retire_capture_urb(snd_usb_substream_t *subs, ...@@ -378,6 +370,10 @@ static int retire_capture_urb(snd_usb_substream_t *subs,
if (subs->hwptr_done >= runtime->buffer_size) if (subs->hwptr_done >= runtime->buffer_size)
subs->hwptr_done -= runtime->buffer_size; subs->hwptr_done -= runtime->buffer_size;
subs->transfer_done += len; subs->transfer_done += len;
if (subs->transfer_done >= runtime->period_size) {
subs->transfer_done -= runtime->period_size;
period_elapsed = 1;
}
spin_unlock_irqrestore(&subs->lock, flags); spin_unlock_irqrestore(&subs->lock, flags);
/* copy a data chunk */ /* copy a data chunk */
if (oldptr + len > runtime->buffer_size) { if (oldptr + len > runtime->buffer_size) {
...@@ -388,15 +384,9 @@ static int retire_capture_urb(snd_usb_substream_t *subs, ...@@ -388,15 +384,9 @@ static int retire_capture_urb(snd_usb_substream_t *subs,
} else { } else {
memcpy(runtime->dma_area + oldptr * stride, cp, len * stride); memcpy(runtime->dma_area + oldptr * stride, cp, len * stride);
} }
/* update the pointer, call callback if necessary */
spin_lock_irqsave(&subs->lock, flags);
if (subs->transfer_done >= runtime->period_size) {
subs->transfer_done -= runtime->period_size;
spin_unlock_irqrestore(&subs->lock, flags);
snd_pcm_period_elapsed(subs->pcm_substream);
} else
spin_unlock_irqrestore(&subs->lock, flags);
} }
if (period_elapsed)
snd_pcm_period_elapsed(subs->pcm_substream);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment