--- /dev/null
+From 245baf983cc39524cce39c24d01b276e6e653c9e Mon Sep 17 00:00:00 2001
+From: Daniel Mack <zonque@gmail.com>
+Date: Thu, 30 Aug 2012 18:52:30 +0200
+Subject: ALSA: snd-usb: fix calls to next_packet_size
+
+From: Daniel Mack <zonque@gmail.com>
+
+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 <zonque@gmail.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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;
--- /dev/null
+From 2e4a263ca80a203ac6109f5932722a716c265395 Mon Sep 17 00:00:00 2001
+From: Daniel Mack <zonque@gmail.com>
+Date: Thu, 30 Aug 2012 18:52:31 +0200
+Subject: ALSA: snd-usb: fix cross-interface streaming devices
+
+From: Daniel Mack <zonque@gmail.com>
+
+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 <zonque@gmail.com>
+Reported-by: Robert M. Albrecht <linux@romal.de>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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;
--- /dev/null
+From 015618b902ae8e28705b7af9b4668615fea48ddd Mon Sep 17 00:00:00 2001
+From: Daniel Mack <zonque@gmail.com>
+Date: Wed, 29 Aug 2012 13:17:05 +0200
+Subject: ALSA: snd-usb: Fix URB cancellation at stream start
+
+From: Daniel Mack <zonque@gmail.com>
+
+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 <zonque@gmail.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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;
+
--- /dev/null
+From fbcfbf5f673847657ccd98afb4d8e13af7fdc372 Mon Sep 17 00:00:00 2001
+From: Daniel Mack <zonque@gmail.com>
+Date: Thu, 30 Aug 2012 18:52:29 +0200
+Subject: ALSA: snd-usb: restore delay information
+
+From: Daniel Mack <zonque@gmail.com>
+
+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 <zonque@gmail.com>
+Cc: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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);
+ }
+
--- /dev/null
+From 03d2f44e967b3c2cf79a6dfb904c8880616c7f83 Mon Sep 17 00:00:00 2001
+From: Pavel Roskin <proski@gnu.org>
+Date: Thu, 30 Aug 2012 17:11:17 -0400
+Subject: ALSA: snd-usb: use list_for_each_safe for endpoint resources
+
+From: Pavel Roskin <proski@gnu.org>
+
+commit 03d2f44e967b3c2cf79a6dfb904c8880616c7f83 upstream.
+
+snd_usb_endpoint_free() frees the structure that contains its argument.
+
+Signed-off-by: Pavel Roskin <proski@gnu.org>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 */
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