From: Greg Kroah-Hartman Date: Fri, 7 Sep 2012 17:13:48 +0000 (-0700) Subject: 3.5-stable patches X-Git-Tag: v3.5.4~17 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d74176adbb7a8388627bae7e11f6114d12a9d778;p=thirdparty%2Fkernel%2Fstable-queue.git 3.5-stable patches added patches: alsa-snd-usb-fix-calls-to-next_packet_size.patch alsa-snd-usb-fix-cross-interface-streaming-devices.patch alsa-snd-usb-fix-urb-cancellation-at-stream-start.patch alsa-snd-usb-restore-delay-information.patch alsa-snd-usb-use-list_for_each_safe-for-endpoint-resources.patch --- diff --git a/queue-3.5/alsa-snd-usb-fix-calls-to-next_packet_size.patch b/queue-3.5/alsa-snd-usb-fix-calls-to-next_packet_size.patch new file mode 100644 index 00000000000..ca23578ec7d --- /dev/null +++ b/queue-3.5/alsa-snd-usb-fix-calls-to-next_packet_size.patch @@ -0,0 +1,113 @@ +From 245baf983cc39524cce39c24d01b276e6e653c9e Mon Sep 17 00:00:00 2001 +From: Daniel Mack +Date: Thu, 30 Aug 2012 18:52:30 +0200 +Subject: ALSA: snd-usb: fix calls to next_packet_size + +From: Daniel Mack + +commit 245baf983cc39524cce39c24d01b276e6e653c9e upstream. + +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 +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/usb/endpoint.c | 13 +------------ + sound/usb/endpoint.h | 1 + + sound/usb/pcm.c | 7 ++++++- + 3 files changed, 8 insertions(+), 13 deletions(-) + +--- a/sound/usb/endpoint.c ++++ b/sound/usb/endpoint.c +@@ -141,7 +141,7 @@ int snd_usb_endpoint_implict_feedback_si + * + * 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; +@@ -177,15 +177,6 @@ static void retire_inbound_urb(struct sn + 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. + */ +@@ -370,7 +361,6 @@ static void snd_complete_urb(struct urb + goto exit_clear; + } + +- prepare_outbound_urb_sizes(ep, ctx); + prepare_outbound_urb(ep, ctx); + } else { + retire_inbound_urb(ep, ctx); +@@ -857,7 +847,6 @@ int snd_usb_endpoint_start(struct snd_us + 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); +--- a/sound/usb/endpoint.h ++++ b/sound/usb/endpoint.h +@@ -21,6 +21,7 @@ int snd_usb_endpoint_deactivate(struct + 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, +--- a/sound/usb/pcm.c ++++ b/sound/usb/pcm.c +@@ -1029,6 +1029,7 @@ static void prepare_playback_urb(struct + 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; +@@ -1040,7 +1041,11 @@ static void prepare_playback_urb(struct + 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; diff --git a/queue-3.5/alsa-snd-usb-fix-cross-interface-streaming-devices.patch b/queue-3.5/alsa-snd-usb-fix-cross-interface-streaming-devices.patch new file mode 100644 index 00000000000..f8972da935f --- /dev/null +++ b/queue-3.5/alsa-snd-usb-fix-cross-interface-streaming-devices.patch @@ -0,0 +1,51 @@ +From 2e4a263ca80a203ac6109f5932722a716c265395 Mon Sep 17 00:00:00 2001 +From: Daniel Mack +Date: Thu, 30 Aug 2012 18:52:31 +0200 +Subject: ALSA: snd-usb: fix cross-interface streaming devices + +From: Daniel Mack + +commit 2e4a263ca80a203ac6109f5932722a716c265395 upstream. + +Commit 68e67f40b ("ALSA: snd-usb: move calls to usb_set_interface") +saved us some unnecessary calls to snd_usb_set_interface() but ignored +the fact that there is at least one device out there which operates on +two endpoint in different interfaces simultaniously. + +Take care for this by catching the case where data and sync endpoints +are located on different interfaces and calling snd_usb_set_interface() +between the start of the two endpoints. + +Signed-off-by: Daniel Mack +Reported-by: Robert M. Albrecht +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/usb/pcm.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/sound/usb/pcm.c ++++ b/sound/usb/pcm.c +@@ -236,6 +236,21 @@ static int start_endpoints(struct snd_us + !test_and_set_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) { + struct snd_usb_endpoint *ep = subs->sync_endpoint; + ++ if (subs->data_endpoint->iface != subs->sync_endpoint->iface || ++ subs->data_endpoint->alt_idx != subs->sync_endpoint->alt_idx) { ++ err = usb_set_interface(subs->dev, ++ subs->sync_endpoint->iface, ++ subs->sync_endpoint->alt_idx); ++ if (err < 0) { ++ snd_printk(KERN_ERR ++ "%d:%d:%d: cannot set interface (%d)\n", ++ subs->dev->devnum, ++ subs->sync_endpoint->iface, ++ subs->sync_endpoint->alt_idx, err); ++ return -EIO; ++ } ++ } ++ + snd_printdd(KERN_DEBUG "Starting sync EP @%p\n", ep); + + ep->sync_slave = subs->data_endpoint; diff --git a/queue-3.5/alsa-snd-usb-fix-urb-cancellation-at-stream-start.patch b/queue-3.5/alsa-snd-usb-fix-urb-cancellation-at-stream-start.patch new file mode 100644 index 00000000000..1befbd17be8 --- /dev/null +++ b/queue-3.5/alsa-snd-usb-fix-urb-cancellation-at-stream-start.patch @@ -0,0 +1,128 @@ +From 015618b902ae8e28705b7af9b4668615fea48ddd Mon Sep 17 00:00:00 2001 +From: Daniel Mack +Date: Wed, 29 Aug 2012 13:17:05 +0200 +Subject: ALSA: snd-usb: Fix URB cancellation at stream start + +From: Daniel Mack + +commit 015618b902ae8e28705b7af9b4668615fea48ddd upstream. + +Commit e9ba389c5 ("ALSA: usb-audio: Fix scheduling-while-atomic bug in +PCM capture stream") fixed a scheduling-while-atomic bug that happened +when snd_usb_endpoint_start was called from the trigger callback, which +is an atmic context. However, the patch breaks the idea of the endpoints +reference counting, which is the reason why the driver has been +refactored lately. + +Revert that commit and let snd_usb_endpoint_start() take care of the URB +cancellation again. As this function is called from both atomic and +non-atomic context, add a flag to denote whether the function may sleep. + +Signed-off-by: Daniel Mack +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/usb/endpoint.c | 11 +++++++++-- + sound/usb/endpoint.h | 2 +- + sound/usb/pcm.c | 13 +++++-------- + 3 files changed, 15 insertions(+), 11 deletions(-) + +--- a/sound/usb/endpoint.c ++++ b/sound/usb/endpoint.c +@@ -799,7 +799,9 @@ int snd_usb_endpoint_set_params(struct s + /** + * snd_usb_endpoint_start: start an snd_usb_endpoint + * +- * @ep: the endpoint to start ++ * @ep: the endpoint to start ++ * @can_sleep: flag indicating whether the operation is executed in ++ * non-atomic context + * + * A call to this function will increment the use count of the endpoint. + * In case it is not already running, the URBs for this endpoint will be +@@ -809,7 +811,7 @@ int snd_usb_endpoint_set_params(struct s + * + * Returns an error if the URB submission failed, 0 in all other cases. + */ +-int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) ++int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep) + { + int err; + unsigned int i; +@@ -821,6 +823,11 @@ int snd_usb_endpoint_start(struct snd_us + if (++ep->use_count != 1) + return 0; + ++ /* just to be sure */ ++ deactivate_urbs(ep, 0, can_sleep); ++ if (can_sleep) ++ wait_clear_urbs(ep); ++ + ep->active_mask = 0; + ep->unlink_mask = 0; + ep->phase = 0; +--- a/sound/usb/endpoint.h ++++ b/sound/usb/endpoint.h +@@ -13,7 +13,7 @@ int snd_usb_endpoint_set_params(struct s + struct audioformat *fmt, + struct snd_usb_endpoint *sync_ep); + +-int snd_usb_endpoint_start(struct snd_usb_endpoint *ep); ++int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep); + void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, + int force, int can_sleep, int wait); + int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep); +--- a/sound/usb/pcm.c ++++ b/sound/usb/pcm.c +@@ -212,7 +212,7 @@ int snd_usb_init_pitch(struct snd_usb_au + } + } + +-static int start_endpoints(struct snd_usb_substream *subs) ++static int start_endpoints(struct snd_usb_substream *subs, int can_sleep) + { + int err; + +@@ -225,7 +225,7 @@ static int start_endpoints(struct snd_us + snd_printdd(KERN_DEBUG "Starting data EP @%p\n", ep); + + ep->data_subs = subs; +- err = snd_usb_endpoint_start(ep); ++ err = snd_usb_endpoint_start(ep, can_sleep); + if (err < 0) { + clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags); + return err; +@@ -239,7 +239,7 @@ static int start_endpoints(struct snd_us + snd_printdd(KERN_DEBUG "Starting sync EP @%p\n", ep); + + ep->sync_slave = subs->data_endpoint; +- err = snd_usb_endpoint_start(ep); ++ err = snd_usb_endpoint_start(ep, can_sleep); + if (err < 0) { + clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags); + return err; +@@ -544,13 +544,10 @@ static int snd_usb_pcm_prepare(struct sn + subs->last_frame_number = 0; + runtime->delay = 0; + +- /* clear the pending deactivation on the target EPs */ +- deactivate_endpoints(subs); +- + /* for playback, submit the URBs now; otherwise, the first hwptr_done + * updates for all URBs would happen at the same time when starting */ + if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) +- return start_endpoints(subs); ++ return start_endpoints(subs, 1); + + return 0; + } +@@ -1175,7 +1172,7 @@ static int snd_usb_substream_capture_tri + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: +- err = start_endpoints(subs); ++ err = start_endpoints(subs, 0); + if (err < 0) + return err; + diff --git a/queue-3.5/alsa-snd-usb-restore-delay-information.patch b/queue-3.5/alsa-snd-usb-restore-delay-information.patch new file mode 100644 index 00000000000..066f9064a94 --- /dev/null +++ b/queue-3.5/alsa-snd-usb-restore-delay-information.patch @@ -0,0 +1,74 @@ +From fbcfbf5f673847657ccd98afb4d8e13af7fdc372 Mon Sep 17 00:00:00 2001 +From: Daniel Mack +Date: Thu, 30 Aug 2012 18:52:29 +0200 +Subject: ALSA: snd-usb: restore delay information + +From: Daniel Mack + +commit fbcfbf5f673847657ccd98afb4d8e13af7fdc372 upstream. + +Parts of commit 294c4fb8 ("ALSA: usb: refine delay information with USB +frame counter") were unfortunately lost during the refactoring of the +snd-usb driver in 3.5. + +This patch adds them back, restoring the correct delay information +behaviour. + +Signed-off-by: Daniel Mack +Cc: Pierre-Louis Bossart +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/usb/pcm.c | 29 ++++++++++++++++++++++++++--- + 1 file changed, 26 insertions(+), 3 deletions(-) + +--- a/sound/usb/pcm.c ++++ b/sound/usb/pcm.c +@@ -1091,7 +1091,16 @@ static void prepare_playback_urb(struct + subs->hwptr_done += bytes; + if (subs->hwptr_done >= runtime->buffer_size * stride) + subs->hwptr_done -= runtime->buffer_size * stride; ++ ++ /* update delay with exact number of samples queued */ ++ runtime->delay = subs->last_delay; + runtime->delay += frames; ++ subs->last_delay = runtime->delay; ++ ++ /* realign last_frame_number */ ++ subs->last_frame_number = usb_get_current_frame_number(subs->dev); ++ subs->last_frame_number &= 0xFF; /* keep 8 LSBs */ ++ + spin_unlock_irqrestore(&subs->lock, flags); + urb->transfer_buffer_length = bytes; + if (period_elapsed) +@@ -1109,12 +1118,26 @@ static void retire_playback_urb(struct s + struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; + int stride = runtime->frame_bits >> 3; + int processed = urb->transfer_buffer_length / stride; ++ int est_delay; + + spin_lock_irqsave(&subs->lock, flags); +- if (processed > runtime->delay) +- runtime->delay = 0; ++ est_delay = snd_usb_pcm_delay(subs, runtime->rate); ++ /* update delay with exact number of samples played */ ++ if (processed > subs->last_delay) ++ subs->last_delay = 0; + else +- runtime->delay -= processed; ++ subs->last_delay -= processed; ++ runtime->delay = subs->last_delay; ++ ++ /* ++ * Report when delay estimate is off by more than 2ms. ++ * The error should be lower than 2ms since the estimate relies ++ * on two reads of a counter updated every ms. ++ */ ++ if (abs(est_delay - subs->last_delay) * 1000 > runtime->rate * 2) ++ snd_printk(KERN_DEBUG "delay: estimated %d, actual %d\n", ++ est_delay, subs->last_delay); ++ + spin_unlock_irqrestore(&subs->lock, flags); + } + diff --git a/queue-3.5/alsa-snd-usb-use-list_for_each_safe-for-endpoint-resources.patch b/queue-3.5/alsa-snd-usb-use-list_for_each_safe-for-endpoint-resources.patch new file mode 100644 index 00000000000..51b4dccc669 --- /dev/null +++ b/queue-3.5/alsa-snd-usb-use-list_for_each_safe-for-endpoint-resources.patch @@ -0,0 +1,39 @@ +From 03d2f44e967b3c2cf79a6dfb904c8880616c7f83 Mon Sep 17 00:00:00 2001 +From: Pavel Roskin +Date: Thu, 30 Aug 2012 17:11:17 -0400 +Subject: ALSA: snd-usb: use list_for_each_safe for endpoint resources + +From: Pavel Roskin + +commit 03d2f44e967b3c2cf79a6dfb904c8880616c7f83 upstream. + +snd_usb_endpoint_free() frees the structure that contains its argument. + +Signed-off-by: Pavel Roskin +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/usb/card.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/sound/usb/card.c ++++ b/sound/usb/card.c +@@ -553,7 +553,7 @@ static void snd_usb_audio_disconnect(str + struct snd_usb_audio *chip) + { + struct snd_card *card; +- struct list_head *p; ++ struct list_head *p, *n; + + if (chip == (void *)-1L) + return; +@@ -570,7 +570,7 @@ static void snd_usb_audio_disconnect(str + snd_usb_stream_disconnect(p); + } + /* release the endpoint resources */ +- list_for_each(p, &chip->ep_list) { ++ list_for_each_safe(p, n, &chip->ep_list) { + snd_usb_endpoint_free(p); + } + /* release the midi resources */ diff --git a/queue-3.5/series b/queue-3.5/series index 3d81002c841..e77ac882058 100644 --- a/queue-3.5/series +++ b/queue-3.5/series @@ -70,3 +70,8 @@ usb-p54usb-remove-__devinit-from-the-struct-usb_device_id-table.patch usb-rtl8187-remove-__devinit-from-the-struct-usb_device_id-table.patch usb-smsusb-remove-__devinit-from-the-struct-usb_device_id-table.patch usb-cdc-acm-fix-null-pointer-dereference.patch +alsa-snd-usb-fix-urb-cancellation-at-stream-start.patch +alsa-snd-usb-use-list_for_each_safe-for-endpoint-resources.patch +alsa-snd-usb-restore-delay-information.patch +alsa-snd-usb-fix-calls-to-next_packet_size.patch +alsa-snd-usb-fix-cross-interface-streaming-devices.patch