Skip to content

Commit

Permalink
ALSA: snd-usb: fix calls to next_packet_size
Browse files Browse the repository at this point in the history
In order to support devices with implicit feedback streaming models,
packet sizes are now stored with each individual urb, and the PCM
handling code which fills the buffers purely relies on the size fields
now.

However, calling snd_usb_audio_next_packet_size() for all possible
packets in an URB at once, prior to letting the PCM code do its job
does in fact not lead to the same behaviour than what the old code did:
The PCM code will break its loop once a period boundary is reached,
consequently using up less packets that it really could.

As snd_usb_audio_next_packet_size() implements a feedback mechanism to
the endpoints phase accumulator, the number of calls to that function
matters, and when called too often, the data rate runs out of bounds.

Fix this by making the next_packet function public, and call it from the
PCM code as before if the packet data sizes are not defined.

Signed-off-by: Daniel Mack <zonque@gmail.com>
Cc: stable@kernel.org [v3.5+]
Signed-off-by: Takashi Iwai <tiwai@suse.de>
  • Loading branch information
Daniel Mack authored and Takashi Iwai committed Aug 31, 2012
1 parent fbcfbf5 commit 245baf9
Show file tree
Hide file tree
Showing 3 changed files with 8 additions and 13 deletions.
13 changes: 1 addition & 12 deletions sound/usb/endpoint.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ int snd_usb_endpoint_implict_feedback_sink(struct snd_usb_endpoint *ep)
*
* For implicit feedback, next_packet_size() is unused.
*/
static int next_packet_size(struct snd_usb_endpoint *ep)
int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep)
{
unsigned long flags;
int ret;
Expand Down Expand Up @@ -177,15 +177,6 @@ static void retire_inbound_urb(struct snd_usb_endpoint *ep,
ep->retire_data_urb(ep->data_subs, urb);
}

static void prepare_outbound_urb_sizes(struct snd_usb_endpoint *ep,
struct snd_urb_ctx *ctx)
{
int i;

for (i = 0; i < ctx->packets; ++i)
ctx->packet_size[i] = next_packet_size(ep);
}

/*
* Prepare a PLAYBACK urb for submission to the bus.
*/
Expand Down Expand Up @@ -370,7 +361,6 @@ static void snd_complete_urb(struct urb *urb)
goto exit_clear;
}

prepare_outbound_urb_sizes(ep, ctx);
prepare_outbound_urb(ep, ctx);
} else {
retire_inbound_urb(ep, ctx);
Expand Down Expand Up @@ -857,7 +847,6 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep)
goto __error;

if (usb_pipeout(ep->pipe)) {
prepare_outbound_urb_sizes(ep, urb->context);
prepare_outbound_urb(ep, urb->context);
} else {
prepare_inbound_urb(ep, urb->context);
Expand Down
1 change: 1 addition & 0 deletions sound/usb/endpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep);
void snd_usb_endpoint_free(struct list_head *head);

int snd_usb_endpoint_implict_feedback_sink(struct snd_usb_endpoint *ep);
int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep);

void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
struct snd_usb_endpoint *sender,
Expand Down
7 changes: 6 additions & 1 deletion sound/usb/pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1029,6 +1029,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
struct urb *urb)
{
struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
struct snd_usb_endpoint *ep = subs->data_endpoint;
struct snd_urb_ctx *ctx = urb->context;
unsigned int counts, frames, bytes;
int i, stride, period_elapsed = 0;
Expand All @@ -1040,7 +1041,11 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
urb->number_of_packets = 0;
spin_lock_irqsave(&subs->lock, flags);
for (i = 0; i < ctx->packets; i++) {
counts = ctx->packet_size[i];
if (ctx->packet_size[i])
counts = ctx->packet_size[i];
else
counts = snd_usb_endpoint_next_packet_size(ep);

/* set up descriptor */
urb->iso_frame_desc[i].offset = frames * stride;
urb->iso_frame_desc[i].length = counts * stride;
Expand Down

0 comments on commit 245baf9

Please sign in to comment.