]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.3-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 14 Feb 2016 20:26:58 +0000 (12:26 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 14 Feb 2016 20:26:58 +0000 (12:26 -0800)
added patches:
alsa-bebob-use-a-signed-return-type-for-get_formation_index.patch
alsa-compress-disable-get_codec_caps-ioctl-for-some-architectures.patch
alsa-dummy-disable-switching-timer-backend-via-sysfs.patch
alsa-dummy-implement-timer-backend-switching-more-safely.patch
alsa-hda-add-fixup-for-mac-mini-7-1-model.patch
alsa-hda-fix-bad-dereference-of-jack-object.patch
alsa-hda-fix-speaker-output-from-vaio-aio-machines.patch
alsa-hda-fix-static-checker-warning-in-patch_hdmi.c.patch
alsa-pcm-fix-potential-deadlock-in-oss-emulation.patch
alsa-rawmidi-fix-race-at-copying-updating-the-position.patch
alsa-rawmidi-make-snd_rawmidi_transmit-race-free.patch
alsa-rawmidi-remove-kernel-warning-for-null-user-space-buffer-check.patch
alsa-seq-degrade-the-error-message-for-too-many-opens.patch
alsa-seq-fix-incorrect-sanity-check-at-snd_seq_oss_synth_cleanup.patch
alsa-seq-fix-lockdep-warnings-due-to-double-mutex-locks.patch
alsa-seq-fix-race-at-closing-in-virmidi-driver.patch
alsa-seq-fix-yet-another-races-among-alsa-timer-accesses.patch
alsa-timer-fix-leftover-link-at-closing.patch
alsa-timer-fix-link-corruption-due-to-double-start-or-stop.patch
alsa-timer-fix-race-at-concurrent-reads.patch
alsa-timer-fix-wrong-instance-passed-to-slave-callbacks.patch
alsa-usb-audio-add-native-dsd-support-for-ps-audio-nuwave-dac.patch
alsa-usb-audio-add-quirk-for-microsoft-lifecam-hd-6000.patch
alsa-usb-audio-avoid-freeing-umidi-object-twice.patch
alsa-usb-audio-fix-oppo-ha-1-vendor-id.patch
alsa-usb-audio-fix-teac-ud-501-ud-503-nt-503-usb-delay.patch
asoc-dpcm-fix-the-be-state-on-hw_free.patch
asoc-rt5645-fix-the-shift-bit-of-in1-boost.patch
hrtimer-handle-remaining-time-proper-for-time_low_res.patch
n_tty-fix-poll-after-buffer-limited-eof-push-read.patch
n_tty-fix-unsafe-reference-to-other-ldisc.patch
revert-alsa-hda-fix-noise-on-gigabyte-z170x-mobo.patch
saa7134-alsa-only-frees-registered-sound-cards.patch
tty-fix-gpf-in-flush_to_ldisc.patch
tty-fix-unsafe-ldisc-reference-via-ioctl-tiocgetd.patch
tty-retry-failed-reopen-if-tty-teardown-in-progress.patch
usb-cdc-acm-handle-unlinked-urb-in-acm-read-callback.patch
usb-cdc-acm-send-zero-packet-for-intel-7260-modem.patch
usb-cp210x-add-id-for-iai-usb-to-rs485-adaptor.patch
usb-hub-do-not-clear-bos-field-during-reset-device.patch
usb-option-fix-cinterion-ahxx-enumeration.patch
usb-phy-msm-fix-error-handling-in-probe.patch
usb-serial-ftdi_sio-add-support-for-yaesu-scu-18-cable.patch
usb-serial-option-adding-support-for-telit-le922.patch
usb-serial-visor-fix-crash-on-detecting-device-without-write_urbs.patch
usb-visor-fix-null-deref-at-probe.patch
usb-xhci-apply-xhci_pme_stuck_quirk-to-intel-broxton-m-platforms.patch
usb-xhci-handle-both-ssic-ports-in-pme-stuck-quirk.patch

49 files changed:
queue-4.3/alsa-bebob-use-a-signed-return-type-for-get_formation_index.patch [new file with mode: 0644]
queue-4.3/alsa-compress-disable-get_codec_caps-ioctl-for-some-architectures.patch [new file with mode: 0644]
queue-4.3/alsa-dummy-disable-switching-timer-backend-via-sysfs.patch [new file with mode: 0644]
queue-4.3/alsa-dummy-implement-timer-backend-switching-more-safely.patch [new file with mode: 0644]
queue-4.3/alsa-hda-add-fixup-for-mac-mini-7-1-model.patch [new file with mode: 0644]
queue-4.3/alsa-hda-fix-bad-dereference-of-jack-object.patch [new file with mode: 0644]
queue-4.3/alsa-hda-fix-speaker-output-from-vaio-aio-machines.patch [new file with mode: 0644]
queue-4.3/alsa-hda-fix-static-checker-warning-in-patch_hdmi.c.patch [new file with mode: 0644]
queue-4.3/alsa-pcm-fix-potential-deadlock-in-oss-emulation.patch [new file with mode: 0644]
queue-4.3/alsa-rawmidi-fix-race-at-copying-updating-the-position.patch [new file with mode: 0644]
queue-4.3/alsa-rawmidi-make-snd_rawmidi_transmit-race-free.patch [new file with mode: 0644]
queue-4.3/alsa-rawmidi-remove-kernel-warning-for-null-user-space-buffer-check.patch [new file with mode: 0644]
queue-4.3/alsa-seq-degrade-the-error-message-for-too-many-opens.patch [new file with mode: 0644]
queue-4.3/alsa-seq-fix-incorrect-sanity-check-at-snd_seq_oss_synth_cleanup.patch [new file with mode: 0644]
queue-4.3/alsa-seq-fix-lockdep-warnings-due-to-double-mutex-locks.patch [new file with mode: 0644]
queue-4.3/alsa-seq-fix-race-at-closing-in-virmidi-driver.patch [new file with mode: 0644]
queue-4.3/alsa-seq-fix-yet-another-races-among-alsa-timer-accesses.patch [new file with mode: 0644]
queue-4.3/alsa-timer-fix-leftover-link-at-closing.patch [new file with mode: 0644]
queue-4.3/alsa-timer-fix-link-corruption-due-to-double-start-or-stop.patch [new file with mode: 0644]
queue-4.3/alsa-timer-fix-race-at-concurrent-reads.patch [new file with mode: 0644]
queue-4.3/alsa-timer-fix-wrong-instance-passed-to-slave-callbacks.patch [new file with mode: 0644]
queue-4.3/alsa-usb-audio-add-native-dsd-support-for-ps-audio-nuwave-dac.patch [new file with mode: 0644]
queue-4.3/alsa-usb-audio-add-quirk-for-microsoft-lifecam-hd-6000.patch [new file with mode: 0644]
queue-4.3/alsa-usb-audio-avoid-freeing-umidi-object-twice.patch [new file with mode: 0644]
queue-4.3/alsa-usb-audio-fix-oppo-ha-1-vendor-id.patch [new file with mode: 0644]
queue-4.3/alsa-usb-audio-fix-teac-ud-501-ud-503-nt-503-usb-delay.patch [new file with mode: 0644]
queue-4.3/asoc-dpcm-fix-the-be-state-on-hw_free.patch [new file with mode: 0644]
queue-4.3/asoc-rt5645-fix-the-shift-bit-of-in1-boost.patch [new file with mode: 0644]
queue-4.3/hrtimer-handle-remaining-time-proper-for-time_low_res.patch [new file with mode: 0644]
queue-4.3/n_tty-fix-poll-after-buffer-limited-eof-push-read.patch [new file with mode: 0644]
queue-4.3/n_tty-fix-unsafe-reference-to-other-ldisc.patch [new file with mode: 0644]
queue-4.3/revert-alsa-hda-fix-noise-on-gigabyte-z170x-mobo.patch [new file with mode: 0644]
queue-4.3/saa7134-alsa-only-frees-registered-sound-cards.patch [new file with mode: 0644]
queue-4.3/series
queue-4.3/tty-fix-gpf-in-flush_to_ldisc.patch [new file with mode: 0644]
queue-4.3/tty-fix-unsafe-ldisc-reference-via-ioctl-tiocgetd.patch [new file with mode: 0644]
queue-4.3/tty-retry-failed-reopen-if-tty-teardown-in-progress.patch [new file with mode: 0644]
queue-4.3/usb-cdc-acm-handle-unlinked-urb-in-acm-read-callback.patch [new file with mode: 0644]
queue-4.3/usb-cdc-acm-send-zero-packet-for-intel-7260-modem.patch [new file with mode: 0644]
queue-4.3/usb-cp210x-add-id-for-iai-usb-to-rs485-adaptor.patch [new file with mode: 0644]
queue-4.3/usb-hub-do-not-clear-bos-field-during-reset-device.patch [new file with mode: 0644]
queue-4.3/usb-option-fix-cinterion-ahxx-enumeration.patch [new file with mode: 0644]
queue-4.3/usb-phy-msm-fix-error-handling-in-probe.patch [new file with mode: 0644]
queue-4.3/usb-serial-ftdi_sio-add-support-for-yaesu-scu-18-cable.patch [new file with mode: 0644]
queue-4.3/usb-serial-option-adding-support-for-telit-le922.patch [new file with mode: 0644]
queue-4.3/usb-serial-visor-fix-crash-on-detecting-device-without-write_urbs.patch [new file with mode: 0644]
queue-4.3/usb-visor-fix-null-deref-at-probe.patch [new file with mode: 0644]
queue-4.3/usb-xhci-apply-xhci_pme_stuck_quirk-to-intel-broxton-m-platforms.patch [new file with mode: 0644]
queue-4.3/usb-xhci-handle-both-ssic-ports-in-pme-stuck-quirk.patch [new file with mode: 0644]

diff --git a/queue-4.3/alsa-bebob-use-a-signed-return-type-for-get_formation_index.patch b/queue-4.3/alsa-bebob-use-a-signed-return-type-for-get_formation_index.patch
new file mode 100644 (file)
index 0000000..96535c0
--- /dev/null
@@ -0,0 +1,61 @@
+From 07905298e4d5777eb58516cdc242f7ac1ca387a2 Mon Sep 17 00:00:00 2001
+From: Lucas Tanure <tanure@linux.com>
+Date: Mon, 25 Jan 2016 19:30:23 -0200
+Subject: ALSA: bebob: Use a signed return type for get_formation_index
+
+From: Lucas Tanure <tanure@linux.com>
+
+commit 07905298e4d5777eb58516cdc242f7ac1ca387a2 upstream.
+
+The return type "unsigned int" was used by the get_formation_index function
+despite of the aspect that it will eventually return a negative        error code.
+So, change to signed int and get index by reference in the parameters.
+
+Done with the help of Coccinelle.
+
+[Fix the missing braces suggested by Julia Lawall -- tiwai]
+
+Signed-off-by: Lucas Tanure <tanure@linux.com>
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Tested-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/firewire/bebob/bebob_stream.c |   14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+--- a/sound/firewire/bebob/bebob_stream.c
++++ b/sound/firewire/bebob/bebob_stream.c
+@@ -47,14 +47,16 @@ static const unsigned int bridgeco_freq_
+       [6] = 0x07,
+ };
+-static unsigned int
+-get_formation_index(unsigned int rate)
++static int
++get_formation_index(unsigned int rate, unsigned int *index)
+ {
+       unsigned int i;
+       for (i = 0; i < ARRAY_SIZE(snd_bebob_rate_table); i++) {
+-              if (snd_bebob_rate_table[i] == rate)
+-                      return i;
++              if (snd_bebob_rate_table[i] == rate) {
++                      *index = i;
++                      return 0;
++              }
+       }
+       return -EINVAL;
+ }
+@@ -424,7 +426,9 @@ make_both_connections(struct snd_bebob *
+               goto end;
+       /* confirm params for both streams */
+-      index = get_formation_index(rate);
++      err = get_formation_index(rate, &index);
++      if (err < 0)
++              goto end;
+       pcm_channels = bebob->tx_stream_formations[index].pcm;
+       midi_channels = bebob->tx_stream_formations[index].midi;
+       amdtp_stream_set_parameters(&bebob->tx_stream,
diff --git a/queue-4.3/alsa-compress-disable-get_codec_caps-ioctl-for-some-architectures.patch b/queue-4.3/alsa-compress-disable-get_codec_caps-ioctl-for-some-architectures.patch
new file mode 100644 (file)
index 0000000..08d39e3
--- /dev/null
@@ -0,0 +1,74 @@
+From 462b3f161beb62eeb290f4ec52f5ead29a2f8ac7 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 25 Jan 2016 13:59:21 +0100
+Subject: ALSA: compress: Disable GET_CODEC_CAPS ioctl for some architectures
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 462b3f161beb62eeb290f4ec52f5ead29a2f8ac7 upstream.
+
+Some architectures like PowerPC can handle the maximum struct size in
+an ioctl only up to 13 bits, and struct snd_compr_codec_caps used by
+SNDRV_COMPRESS_GET_CODEC_CAPS ioctl overflows this limit.  This
+problem was revealed recently by a powerpc change, as it's now treated
+as a fatal build error.
+
+This patch is a stop-gap for that: for architectures with less than 14
+bit ioctl struct size, get rid of the handling of the relevant ioctl.
+We should provide an alternative equivalent ioctl code later, but for
+now just paper over it.  Luckily, the compress API hasn't been used on
+such architectures, so the impact must be effectively zero.
+
+Reviewed-by: Mark Brown <broonie@kernel.org>
+Acked-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/compress_offload.c |   11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+--- a/sound/core/compress_offload.c
++++ b/sound/core/compress_offload.c
+@@ -44,6 +44,13 @@
+ #include <sound/compress_offload.h>
+ #include <sound/compress_driver.h>
++/* struct snd_compr_codec_caps overflows the ioctl bit size for some
++ * architectures, so we need to disable the relevant ioctls.
++ */
++#if _IOC_SIZEBITS < 14
++#define COMPR_CODEC_CAPS_OVERFLOW
++#endif
++
+ /* TODO:
+  * - add substream support for multiple devices in case of
+  *    SND_DYNAMIC_MINORS is not used
+@@ -438,6 +445,7 @@ out:
+       return retval;
+ }
++#ifndef COMPR_CODEC_CAPS_OVERFLOW
+ static int
+ snd_compr_get_codec_caps(struct snd_compr_stream *stream, unsigned long arg)
+ {
+@@ -461,6 +469,7 @@ out:
+       kfree(caps);
+       return retval;
+ }
++#endif /* !COMPR_CODEC_CAPS_OVERFLOW */
+ /* revisit this with snd_pcm_preallocate_xxx */
+ static int snd_compr_allocate_buffer(struct snd_compr_stream *stream,
+@@ -799,9 +808,11 @@ static long snd_compr_ioctl(struct file
+       case _IOC_NR(SNDRV_COMPRESS_GET_CAPS):
+               retval = snd_compr_get_caps(stream, arg);
+               break;
++#ifndef COMPR_CODEC_CAPS_OVERFLOW
+       case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS):
+               retval = snd_compr_get_codec_caps(stream, arg);
+               break;
++#endif
+       case _IOC_NR(SNDRV_COMPRESS_SET_PARAMS):
+               retval = snd_compr_set_params(stream, arg);
+               break;
diff --git a/queue-4.3/alsa-dummy-disable-switching-timer-backend-via-sysfs.patch b/queue-4.3/alsa-dummy-disable-switching-timer-backend-via-sysfs.patch
new file mode 100644 (file)
index 0000000..49ccb68
--- /dev/null
@@ -0,0 +1,39 @@
+From 7ee96216c31aabe1eb42fb91ff50dae9fcd014b2 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Thu, 28 Jan 2016 07:54:16 +0100
+Subject: ALSA: dummy: Disable switching timer backend via sysfs
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 7ee96216c31aabe1eb42fb91ff50dae9fcd014b2 upstream.
+
+ALSA dummy driver can switch the timer backend between system timer
+and hrtimer via its hrtimer module option.  This can be also switched
+dynamically via sysfs, but it may lead to a memory corruption when
+switching is done while a PCM stream is running; the stream instance
+for the newly switched timer method tries to access the memory that
+was allocated by another timer method although the sizes differ.
+
+As the simplest fix, this patch just disables the switch via sysfs by
+dropping the writable bit.
+
+BugLink: http://lkml.kernel.org/r/CACT4Y+ZGEeEBntHW5WHn2GoeE0G_kRrCmUh6=dWyy-wfzvuJLg@mail.gmail.com
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/drivers/dummy.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sound/drivers/dummy.c
++++ b/sound/drivers/dummy.c
+@@ -87,7 +87,7 @@ MODULE_PARM_DESC(pcm_substreams, "PCM su
+ module_param(fake_buffer, bool, 0444);
+ MODULE_PARM_DESC(fake_buffer, "Fake buffer allocations.");
+ #ifdef CONFIG_HIGH_RES_TIMERS
+-module_param(hrtimer, bool, 0644);
++module_param(hrtimer, bool, 0444);
+ MODULE_PARM_DESC(hrtimer, "Use hrtimer as the timer source.");
+ #endif
diff --git a/queue-4.3/alsa-dummy-implement-timer-backend-switching-more-safely.patch b/queue-4.3/alsa-dummy-implement-timer-backend-switching-more-safely.patch
new file mode 100644 (file)
index 0000000..26d650a
--- /dev/null
@@ -0,0 +1,174 @@
+From ddce57a6f0a2d8d1bfacfa77f06043bc760403c2 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 2 Feb 2016 15:27:36 +0100
+Subject: ALSA: dummy: Implement timer backend switching more safely
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit ddce57a6f0a2d8d1bfacfa77f06043bc760403c2 upstream.
+
+Currently the selected timer backend is referred at any moment from
+the running PCM callbacks.  When the backend is switched, it's
+possible to lead to inconsistency from the running backend.  This was
+pointed by syzkaller fuzzer, and the commit [7ee96216c31a: ALSA:
+dummy: Disable switching timer backend via sysfs] disabled the dynamic
+switching for avoiding the crash.
+
+This patch improves the handling of timer backend switching.  It keeps
+the reference to the selected backend during the whole operation of an
+opened stream so that it won't be changed by other streams.
+
+Together with this change, the hrtimer parameter is reenabled as
+writable now.
+
+NOTE: this patch also turned out to fix the still remaining race.
+Namely, ops was still replaced dynamically at dummy_pcm_open:
+
+  static int dummy_pcm_open(struct snd_pcm_substream *substream)
+  {
+  ....
+          dummy->timer_ops = &dummy_systimer_ops;
+          if (hrtimer)
+                  dummy->timer_ops = &dummy_hrtimer_ops;
+
+Since dummy->timer_ops is common among all streams, and when the
+replacement happens during accesses of other streams, it may lead to a
+crash.  This was actually triggered by syzkaller fuzzer and KASAN.
+
+This patch rewrites the code not to use the ops shared by all streams
+any longer, too.
+
+BugLink: http://lkml.kernel.org/r/CACT4Y+aZ+xisrpuM6cOXbL21DuM0yVxPYXf4cD4Md9uw0C3dBQ@mail.gmail.com
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/drivers/dummy.c |   37 +++++++++++++++++++------------------
+ 1 file changed, 19 insertions(+), 18 deletions(-)
+
+--- a/sound/drivers/dummy.c
++++ b/sound/drivers/dummy.c
+@@ -87,7 +87,7 @@ MODULE_PARM_DESC(pcm_substreams, "PCM su
+ module_param(fake_buffer, bool, 0444);
+ MODULE_PARM_DESC(fake_buffer, "Fake buffer allocations.");
+ #ifdef CONFIG_HIGH_RES_TIMERS
+-module_param(hrtimer, bool, 0444);
++module_param(hrtimer, bool, 0644);
+ MODULE_PARM_DESC(hrtimer, "Use hrtimer as the timer source.");
+ #endif
+@@ -109,6 +109,9 @@ struct dummy_timer_ops {
+       snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *);
+ };
++#define get_dummy_ops(substream) \
++      (*(const struct dummy_timer_ops **)(substream)->runtime->private_data)
++
+ struct dummy_model {
+       const char *name;
+       int (*playback_constraints)(struct snd_pcm_runtime *runtime);
+@@ -137,7 +140,6 @@ struct snd_dummy {
+       int iobox;
+       struct snd_kcontrol *cd_volume_ctl;
+       struct snd_kcontrol *cd_switch_ctl;
+-      const struct dummy_timer_ops *timer_ops;
+ };
+ /*
+@@ -231,6 +233,8 @@ static struct dummy_model *dummy_models[
+  */
+ struct dummy_systimer_pcm {
++      /* ops must be the first item */
++      const struct dummy_timer_ops *timer_ops;
+       spinlock_t lock;
+       struct timer_list timer;
+       unsigned long base_time;
+@@ -366,6 +370,8 @@ static struct dummy_timer_ops dummy_syst
+  */
+ struct dummy_hrtimer_pcm {
++      /* ops must be the first item */
++      const struct dummy_timer_ops *timer_ops;
+       ktime_t base_time;
+       ktime_t period_time;
+       atomic_t running;
+@@ -492,31 +498,25 @@ static struct dummy_timer_ops dummy_hrti
+ static int dummy_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+ {
+-      struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
+-
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+-              return dummy->timer_ops->start(substream);
++              return get_dummy_ops(substream)->start(substream);
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+-              return dummy->timer_ops->stop(substream);
++              return get_dummy_ops(substream)->stop(substream);
+       }
+       return -EINVAL;
+ }
+ static int dummy_pcm_prepare(struct snd_pcm_substream *substream)
+ {
+-      struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
+-
+-      return dummy->timer_ops->prepare(substream);
++      return get_dummy_ops(substream)->prepare(substream);
+ }
+ static snd_pcm_uframes_t dummy_pcm_pointer(struct snd_pcm_substream *substream)
+ {
+-      struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
+-
+-      return dummy->timer_ops->pointer(substream);
++      return get_dummy_ops(substream)->pointer(substream);
+ }
+ static struct snd_pcm_hardware dummy_pcm_hardware = {
+@@ -562,17 +562,19 @@ static int dummy_pcm_open(struct snd_pcm
+       struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
+       struct dummy_model *model = dummy->model;
+       struct snd_pcm_runtime *runtime = substream->runtime;
++      const struct dummy_timer_ops *ops;
+       int err;
+-      dummy->timer_ops = &dummy_systimer_ops;
++      ops = &dummy_systimer_ops;
+ #ifdef CONFIG_HIGH_RES_TIMERS
+       if (hrtimer)
+-              dummy->timer_ops = &dummy_hrtimer_ops;
++              ops = &dummy_hrtimer_ops;
+ #endif
+-      err = dummy->timer_ops->create(substream);
++      err = ops->create(substream);
+       if (err < 0)
+               return err;
++      get_dummy_ops(substream) = ops;
+       runtime->hw = dummy->pcm_hw;
+       if (substream->pcm->device & 1) {
+@@ -594,7 +596,7 @@ static int dummy_pcm_open(struct snd_pcm
+                       err = model->capture_constraints(substream->runtime);
+       }
+       if (err < 0) {
+-              dummy->timer_ops->free(substream);
++              get_dummy_ops(substream)->free(substream);
+               return err;
+       }
+       return 0;
+@@ -602,8 +604,7 @@ static int dummy_pcm_open(struct snd_pcm
+ static int dummy_pcm_close(struct snd_pcm_substream *substream)
+ {
+-      struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
+-      dummy->timer_ops->free(substream);
++      get_dummy_ops(substream)->free(substream);
+       return 0;
+ }
diff --git a/queue-4.3/alsa-hda-add-fixup-for-mac-mini-7-1-model.patch b/queue-4.3/alsa-hda-add-fixup-for-mac-mini-7-1-model.patch
new file mode 100644 (file)
index 0000000..9d80124
--- /dev/null
@@ -0,0 +1,90 @@
+From 2154cc0e2d4ae15132d005d17e473327c70c9a06 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 3 Feb 2016 12:32:51 +0100
+Subject: ALSA: hda - Add fixup for Mac Mini 7,1 model
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 2154cc0e2d4ae15132d005d17e473327c70c9a06 upstream.
+
+Mac Mini 7,1 model with CS4208 codec reports the headphone jack
+detection wrongly in an inverted way.  Moreover, the advertised pins
+for the audio input and SPDIF output have actually no jack detection.
+
+This patch addresses these issues.  The inv_jack_detect flag is set
+for fixing the headphone jack detection, and the pin configs for audio
+input and SPDIF output are marked as non-detectable.
+
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=105161
+Report-and-tested-by: moosotc@gmail.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/pci/hda/patch_cirrus.c |   27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+--- a/sound/pci/hda/patch_cirrus.c
++++ b/sound/pci/hda/patch_cirrus.c
+@@ -613,6 +613,7 @@ enum {
+       CS4208_MAC_AUTO,
+       CS4208_MBA6,
+       CS4208_MBP11,
++      CS4208_MACMINI,
+       CS4208_GPIO0,
+ };
+@@ -620,6 +621,7 @@ static const struct hda_model_fixup cs42
+       { .id = CS4208_GPIO0, .name = "gpio0" },
+       { .id = CS4208_MBA6, .name = "mba6" },
+       { .id = CS4208_MBP11, .name = "mbp11" },
++      { .id = CS4208_MACMINI, .name = "macmini" },
+       {}
+ };
+@@ -631,6 +633,7 @@ static const struct snd_pci_quirk cs4208
+ /* codec SSID matching */
+ static const struct snd_pci_quirk cs4208_mac_fixup_tbl[] = {
+       SND_PCI_QUIRK(0x106b, 0x5e00, "MacBookPro 11,2", CS4208_MBP11),
++      SND_PCI_QUIRK(0x106b, 0x6c00, "MacMini 7,1", CS4208_MACMINI),
+       SND_PCI_QUIRK(0x106b, 0x7100, "MacBookAir 6,1", CS4208_MBA6),
+       SND_PCI_QUIRK(0x106b, 0x7200, "MacBookAir 6,2", CS4208_MBA6),
+       SND_PCI_QUIRK(0x106b, 0x7b00, "MacBookPro 12,1", CS4208_MBP11),
+@@ -665,6 +668,24 @@ static void cs4208_fixup_mac(struct hda_
+       snd_hda_apply_fixup(codec, action);
+ }
++/* MacMini 7,1 has the inverted jack detection */
++static void cs4208_fixup_macmini(struct hda_codec *codec,
++                               const struct hda_fixup *fix, int action)
++{
++      static const struct hda_pintbl pincfgs[] = {
++              { 0x18, 0x00ab9150 }, /* mic (audio-in) jack: disable detect */
++              { 0x21, 0x004be140 }, /* SPDIF: disable detect */
++              { }
++      };
++
++      if (action == HDA_FIXUP_ACT_PRE_PROBE) {
++              /* HP pin (0x10) has an inverted detection */
++              codec->inv_jack_detect = 1;
++              /* disable the bogus Mic and SPDIF jack detections */
++              snd_hda_apply_pincfgs(codec, pincfgs);
++      }
++}
++
+ static int cs4208_spdif_sw_put(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *ucontrol)
+ {
+@@ -708,6 +729,12 @@ static const struct hda_fixup cs4208_fix
+               .chained = true,
+               .chain_id = CS4208_GPIO0,
+       },
++      [CS4208_MACMINI] = {
++              .type = HDA_FIXUP_FUNC,
++              .v.func = cs4208_fixup_macmini,
++              .chained = true,
++              .chain_id = CS4208_GPIO0,
++      },
+       [CS4208_GPIO0] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = cs4208_fixup_gpio0,
diff --git a/queue-4.3/alsa-hda-fix-bad-dereference-of-jack-object.patch b/queue-4.3/alsa-hda-fix-bad-dereference-of-jack-object.patch
new file mode 100644 (file)
index 0000000..ebdf443
--- /dev/null
@@ -0,0 +1,127 @@
+From 2ebab40eb74a0225d5dfba72bfae317dd948fa2d Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 9 Feb 2016 10:23:52 +0100
+Subject: ALSA: hda - Fix bad dereference of jack object
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 2ebab40eb74a0225d5dfba72bfae317dd948fa2d upstream.
+
+The hda_jack_tbl entries are managed by snd_array for allowing
+multiple jacks.  It's good per se, but the problem is that struct
+hda_jack_callback keeps the hda_jack_tbl pointer.  Since snd_array
+doesn't preserve each pointer at resizing the array, we can't keep the
+original pointer but have to deduce the pointer at each time via
+snd_array_entry() instead.  Actually, this resulted in the deference
+to the wrong pointer on codecs that have many pins such as CS4208.
+
+This patch replaces the pointer to the NID value as the search key.
+As an unexpected good side effect, this even simplifies the code, as
+only NID is needed in most cases.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/pci/hda/hda_generic.c    |    4 ++--
+ sound/pci/hda/hda_jack.c       |    2 +-
+ sound/pci/hda/hda_jack.h       |    2 +-
+ sound/pci/hda/patch_ca0132.c   |    5 ++++-
+ sound/pci/hda/patch_hdmi.c     |    2 +-
+ sound/pci/hda/patch_realtek.c  |    2 +-
+ sound/pci/hda/patch_sigmatel.c |    6 +++---
+ 7 files changed, 13 insertions(+), 10 deletions(-)
+
+--- a/sound/pci/hda/hda_generic.c
++++ b/sound/pci/hda/hda_generic.c
+@@ -4045,9 +4045,9 @@ static void pin_power_callback(struct hd
+                              struct hda_jack_callback *jack,
+                              bool on)
+ {
+-      if (jack && jack->tbl->nid)
++      if (jack && jack->nid)
+               sync_power_state_change(codec,
+-                                      set_pin_power_jack(codec, jack->tbl->nid, on));
++                                      set_pin_power_jack(codec, jack->nid, on));
+ }
+ /* callback only doing power up -- called at first */
+--- a/sound/pci/hda/hda_jack.c
++++ b/sound/pci/hda/hda_jack.c
+@@ -259,7 +259,7 @@ snd_hda_jack_detect_enable_callback(stru
+               if (!callback)
+                       return ERR_PTR(-ENOMEM);
+               callback->func = func;
+-              callback->tbl = jack;
++              callback->nid = jack->nid;
+               callback->next = jack->callback;
+               jack->callback = callback;
+       }
+--- a/sound/pci/hda/hda_jack.h
++++ b/sound/pci/hda/hda_jack.h
+@@ -21,7 +21,7 @@ struct hda_jack_callback;
+ typedef void (*hda_jack_callback_fn) (struct hda_codec *, struct hda_jack_callback *);
+ struct hda_jack_callback {
+-      struct hda_jack_tbl *tbl;
++      hda_nid_t nid;
+       hda_jack_callback_fn func;
+       unsigned int private_data;      /* arbitrary data */
+       struct hda_jack_callback *next;
+--- a/sound/pci/hda/patch_ca0132.c
++++ b/sound/pci/hda/patch_ca0132.c
+@@ -4427,13 +4427,16 @@ static void ca0132_process_dsp_response(
+ static void hp_callback(struct hda_codec *codec, struct hda_jack_callback *cb)
+ {
+       struct ca0132_spec *spec = codec->spec;
++      struct hda_jack_tbl *tbl;
+       /* Delay enabling the HP amp, to let the mic-detection
+        * state machine run.
+        */
+       cancel_delayed_work_sync(&spec->unsol_hp_work);
+       schedule_delayed_work(&spec->unsol_hp_work, msecs_to_jiffies(500));
+-      cb->tbl->block_report = 1;
++      tbl = snd_hda_jack_tbl_get(codec, cb->nid);
++      if (tbl)
++              tbl->block_report = 1;
+ }
+ static void amic_callback(struct hda_codec *codec, struct hda_jack_callback *cb)
+--- a/sound/pci/hda/patch_hdmi.c
++++ b/sound/pci/hda/patch_hdmi.c
+@@ -1184,7 +1184,7 @@ static void check_presence_and_report(st
+ static void jack_callback(struct hda_codec *codec,
+                         struct hda_jack_callback *jack)
+ {
+-      check_presence_and_report(codec, jack->tbl->nid);
++      check_presence_and_report(codec, jack->nid);
+ }
+ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -282,7 +282,7 @@ static void alc_update_knob_master(struc
+       uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
+       if (!uctl)
+               return;
+-      val = snd_hda_codec_read(codec, jack->tbl->nid, 0,
++      val = snd_hda_codec_read(codec, jack->nid, 0,
+                                AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
+       val &= HDA_AMP_VOLMASK;
+       uctl->value.integer.value[0] = val;
+--- a/sound/pci/hda/patch_sigmatel.c
++++ b/sound/pci/hda/patch_sigmatel.c
+@@ -493,9 +493,9 @@ static void jack_update_power(struct hda
+       if (!spec->num_pwrs)
+               return;
+-      if (jack && jack->tbl->nid) {
+-              stac_toggle_power_map(codec, jack->tbl->nid,
+-                                    snd_hda_jack_detect(codec, jack->tbl->nid),
++      if (jack && jack->nid) {
++              stac_toggle_power_map(codec, jack->nid,
++                                    snd_hda_jack_detect(codec, jack->nid),
+                                     true);
+               return;
+       }
diff --git a/queue-4.3/alsa-hda-fix-speaker-output-from-vaio-aio-machines.patch b/queue-4.3/alsa-hda-fix-speaker-output-from-vaio-aio-machines.patch
new file mode 100644 (file)
index 0000000..e230504
--- /dev/null
@@ -0,0 +1,30 @@
+From c44d9b1181cf34e0860c72cc8a00e0c47417aac0 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Sun, 7 Feb 2016 09:38:26 +0100
+Subject: ALSA: hda - Fix speaker output from VAIO AiO machines
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit c44d9b1181cf34e0860c72cc8a00e0c47417aac0 upstream.
+
+Some Sony VAIO AiO models (VGC-JS4EF and VGC-JS25G, both with PCI SSID
+104d:9044) need the same quirk to make the speaker working properly.
+
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=112031
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/pci/hda/patch_realtek.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -2231,6 +2231,7 @@ static const struct snd_pci_quirk alc882
+       SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT),
+       SND_PCI_QUIRK(0x104d, 0x905a, "Sony Vaio Z", ALC882_FIXUP_NO_PRIMARY_HP),
+       SND_PCI_QUIRK(0x104d, 0x9043, "Sony Vaio VGC-LN51JGB", ALC882_FIXUP_NO_PRIMARY_HP),
++      SND_PCI_QUIRK(0x104d, 0x9044, "Sony VAIO AiO", ALC882_FIXUP_NO_PRIMARY_HP),
+       /* All Apple entries are in codec SSIDs */
+       SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF),
diff --git a/queue-4.3/alsa-hda-fix-static-checker-warning-in-patch_hdmi.c.patch b/queue-4.3/alsa-hda-fix-static-checker-warning-in-patch_hdmi.c.patch
new file mode 100644 (file)
index 0000000..704c715
--- /dev/null
@@ -0,0 +1,40 @@
+From 360a8245680053619205a3ae10e6bfe624a5da1d Mon Sep 17 00:00:00 2001
+From: David Henningsson <david.henningsson@canonical.com>
+Date: Fri, 5 Feb 2016 09:05:41 +0100
+Subject: ALSA: hda - Fix static checker warning in patch_hdmi.c
+
+From: David Henningsson <david.henningsson@canonical.com>
+
+commit 360a8245680053619205a3ae10e6bfe624a5da1d upstream.
+
+The static checker warning is:
+
+       sound/pci/hda/patch_hdmi.c:460 hdmi_eld_ctl_get()
+       error: __memcpy() 'eld->eld_buffer' too small (256 vs 512)
+
+I have a hard time figuring out if this can ever cause an information leak
+(I don't think so), but nonetheless it does not hurt to increase the
+robustness of the code.
+
+Fixes: 68e03de98507 ('ALSA: hda - hdmi: Do not expose eld data when eld is invalid')
+Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: David Henningsson <david.henningsson@canonical.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/pci/hda/patch_hdmi.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/sound/pci/hda/patch_hdmi.c
++++ b/sound/pci/hda/patch_hdmi.c
+@@ -438,7 +438,8 @@ static int hdmi_eld_ctl_get(struct snd_k
+       eld = &per_pin->sink_eld;
+       mutex_lock(&per_pin->lock);
+-      if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data)) {
++      if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data) ||
++          eld->eld_size > ELD_MAX_SIZE) {
+               mutex_unlock(&per_pin->lock);
+               snd_BUG();
+               return -EINVAL;
diff --git a/queue-4.3/alsa-pcm-fix-potential-deadlock-in-oss-emulation.patch b/queue-4.3/alsa-pcm-fix-potential-deadlock-in-oss-emulation.patch
new file mode 100644 (file)
index 0000000..7078cae
--- /dev/null
@@ -0,0 +1,100 @@
+From b248371628aad599a48540962f6b85a21a8a0c3f Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Sun, 31 Jan 2016 10:32:37 +0100
+Subject: ALSA: pcm: Fix potential deadlock in OSS emulation
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit b248371628aad599a48540962f6b85a21a8a0c3f upstream.
+
+There are potential deadlocks in PCM OSS emulation code while
+accessing read/write and mmap concurrently.  This comes from the
+infamous mmap_sem usage in copy_from/to_user().  Namely,
+
+   snd_pcm_oss_write() ->
+     &runtime->oss.params_lock ->
+        copy_to_user() ->
+          &mm->mmap_sem
+  mmap() ->
+    &mm->mmap_sem ->
+      snd_pcm_oss_mmap() ->
+        &runtime->oss.params_lock
+
+Since we can't avoid taking params_lock from mmap code path, use
+trylock variant and aborts with -EAGAIN as a workaround of this AB/BA
+deadlock.
+
+BugLink: http://lkml.kernel.org/r/CACT4Y+bVrBKDG0G2_AcUgUQa+X91VKTeS4v+wN7BSHwHtqn3kQ@mail.gmail.com
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/oss/pcm_oss.c |   21 +++++++++++++++------
+ 1 file changed, 15 insertions(+), 6 deletions(-)
+
+--- a/sound/core/oss/pcm_oss.c
++++ b/sound/core/oss/pcm_oss.c
+@@ -834,7 +834,8 @@ static int choose_rate(struct snd_pcm_su
+       return snd_pcm_hw_param_near(substream, params, SNDRV_PCM_HW_PARAM_RATE, best_rate, NULL);
+ }
+-static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
++static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream,
++                                   bool trylock)
+ {
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct snd_pcm_hw_params *params, *sparams;
+@@ -848,7 +849,10 @@ static int snd_pcm_oss_change_params(str
+       struct snd_mask sformat_mask;
+       struct snd_mask mask;
+-      if (mutex_lock_interruptible(&runtime->oss.params_lock))
++      if (trylock) {
++              if (!(mutex_trylock(&runtime->oss.params_lock)))
++                      return -EAGAIN;
++      } else if (mutex_lock_interruptible(&runtime->oss.params_lock))
+               return -EINTR;
+       sw_params = kmalloc(sizeof(*sw_params), GFP_KERNEL);
+       params = kmalloc(sizeof(*params), GFP_KERNEL);
+@@ -1092,7 +1096,7 @@ static int snd_pcm_oss_get_active_substr
+               if (asubstream == NULL)
+                       asubstream = substream;
+               if (substream->runtime->oss.params) {
+-                      err = snd_pcm_oss_change_params(substream);
++                      err = snd_pcm_oss_change_params(substream, false);
+                       if (err < 0)
+                               return err;
+               }
+@@ -1132,7 +1136,7 @@ static int snd_pcm_oss_make_ready(struct
+               return 0;
+       runtime = substream->runtime;
+       if (runtime->oss.params) {
+-              err = snd_pcm_oss_change_params(substream);
++              err = snd_pcm_oss_change_params(substream, false);
+               if (err < 0)
+                       return err;
+       }
+@@ -2163,7 +2167,7 @@ static int snd_pcm_oss_get_space(struct
+       runtime = substream->runtime;
+       if (runtime->oss.params &&
+-          (err = snd_pcm_oss_change_params(substream)) < 0)
++          (err = snd_pcm_oss_change_params(substream, false)) < 0)
+               return err;
+       info.fragsize = runtime->oss.period_bytes;
+@@ -2800,7 +2804,12 @@ static int snd_pcm_oss_mmap(struct file
+               return -EIO;
+       
+       if (runtime->oss.params) {
+-              if ((err = snd_pcm_oss_change_params(substream)) < 0)
++              /* use mutex_trylock() for params_lock for avoiding a deadlock
++               * between mmap_sem and params_lock taken by
++               * copy_from/to_user() in snd_pcm_oss_write/read()
++               */
++              err = snd_pcm_oss_change_params(substream, true);
++              if (err < 0)
+                       return err;
+       }
+ #ifdef CONFIG_SND_PCM_OSS_PLUGINS
diff --git a/queue-4.3/alsa-rawmidi-fix-race-at-copying-updating-the-position.patch b/queue-4.3/alsa-rawmidi-fix-race-at-copying-updating-the-position.patch
new file mode 100644 (file)
index 0000000..5ac96c7
--- /dev/null
@@ -0,0 +1,121 @@
+From 81f577542af15640cbcb6ef68baa4caa610cbbfc Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 3 Feb 2016 14:41:22 +0100
+Subject: ALSA: rawmidi: Fix race at copying & updating the position
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 81f577542af15640cbcb6ef68baa4caa610cbbfc upstream.
+
+The rawmidi read and write functions manage runtime stream status
+such as runtime->appl_ptr and runtime->avail.  These point where to
+copy the new data and how many bytes have been copied (or to be
+read).  The problem is that rawmidi read/write call copy_from_user()
+or copy_to_user(), and the runtime spinlock is temporarily unlocked
+and relocked while copying user-space.  Since the current code
+advances and updates the runtime status after the spin unlock/relock,
+the copy and the update may be asynchronous, and eventually
+runtime->avail might go to a negative value when many concurrent
+accesses are done.  This may lead to memory corruption in the end.
+
+For fixing this race, in this patch, the status update code is
+performed in the same lock before the temporary unlock.  Also, the
+spinlock is now taken more widely in snd_rawmidi_kernel_read1() for
+protecting more properly during the whole operation.
+
+BugLink: http://lkml.kernel.org/r/CACT4Y+b-dCmNf1GpgPKfDO0ih+uZCL2JV4__j-r1kdhPLSgQCQ@mail.gmail.com
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Tested-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/rawmidi.c |   34 ++++++++++++++++++++++------------
+ 1 file changed, 22 insertions(+), 12 deletions(-)
+
+--- a/sound/core/rawmidi.c
++++ b/sound/core/rawmidi.c
+@@ -942,31 +942,36 @@ static long snd_rawmidi_kernel_read1(str
+       unsigned long flags;
+       long result = 0, count1;
+       struct snd_rawmidi_runtime *runtime = substream->runtime;
++      unsigned long appl_ptr;
++      spin_lock_irqsave(&runtime->lock, flags);
+       while (count > 0 && runtime->avail) {
+               count1 = runtime->buffer_size - runtime->appl_ptr;
+               if (count1 > count)
+                       count1 = count;
+-              spin_lock_irqsave(&runtime->lock, flags);
+               if (count1 > (int)runtime->avail)
+                       count1 = runtime->avail;
++
++              /* update runtime->appl_ptr before unlocking for userbuf */
++              appl_ptr = runtime->appl_ptr;
++              runtime->appl_ptr += count1;
++              runtime->appl_ptr %= runtime->buffer_size;
++              runtime->avail -= count1;
++
+               if (kernelbuf)
+-                      memcpy(kernelbuf + result, runtime->buffer + runtime->appl_ptr, count1);
++                      memcpy(kernelbuf + result, runtime->buffer + appl_ptr, count1);
+               if (userbuf) {
+                       spin_unlock_irqrestore(&runtime->lock, flags);
+                       if (copy_to_user(userbuf + result,
+-                                       runtime->buffer + runtime->appl_ptr, count1)) {
++                                       runtime->buffer + appl_ptr, count1)) {
+                               return result > 0 ? result : -EFAULT;
+                       }
+                       spin_lock_irqsave(&runtime->lock, flags);
+               }
+-              runtime->appl_ptr += count1;
+-              runtime->appl_ptr %= runtime->buffer_size;
+-              runtime->avail -= count1;
+-              spin_unlock_irqrestore(&runtime->lock, flags);
+               result += count1;
+               count -= count1;
+       }
++      spin_unlock_irqrestore(&runtime->lock, flags);
+       return result;
+ }
+@@ -1223,6 +1228,7 @@ static long snd_rawmidi_kernel_write1(st
+       unsigned long flags;
+       long count1, result;
+       struct snd_rawmidi_runtime *runtime = substream->runtime;
++      unsigned long appl_ptr;
+       if (!kernelbuf && !userbuf)
+               return -EINVAL;
+@@ -1243,12 +1249,19 @@ static long snd_rawmidi_kernel_write1(st
+                       count1 = count;
+               if (count1 > (long)runtime->avail)
+                       count1 = runtime->avail;
++
++              /* update runtime->appl_ptr before unlocking for userbuf */
++              appl_ptr = runtime->appl_ptr;
++              runtime->appl_ptr += count1;
++              runtime->appl_ptr %= runtime->buffer_size;
++              runtime->avail -= count1;
++
+               if (kernelbuf)
+-                      memcpy(runtime->buffer + runtime->appl_ptr,
++                      memcpy(runtime->buffer + appl_ptr,
+                              kernelbuf + result, count1);
+               else if (userbuf) {
+                       spin_unlock_irqrestore(&runtime->lock, flags);
+-                      if (copy_from_user(runtime->buffer + runtime->appl_ptr,
++                      if (copy_from_user(runtime->buffer + appl_ptr,
+                                          userbuf + result, count1)) {
+                               spin_lock_irqsave(&runtime->lock, flags);
+                               result = result > 0 ? result : -EFAULT;
+@@ -1256,9 +1269,6 @@ static long snd_rawmidi_kernel_write1(st
+                       }
+                       spin_lock_irqsave(&runtime->lock, flags);
+               }
+-              runtime->appl_ptr += count1;
+-              runtime->appl_ptr %= runtime->buffer_size;
+-              runtime->avail -= count1;
+               result += count1;
+               count -= count1;
+       }
diff --git a/queue-4.3/alsa-rawmidi-make-snd_rawmidi_transmit-race-free.patch b/queue-4.3/alsa-rawmidi-make-snd_rawmidi_transmit-race-free.patch
new file mode 100644 (file)
index 0000000..aecc64d
--- /dev/null
@@ -0,0 +1,305 @@
+From 06ab30034ed9c200a570ab13c017bde248ddb2a6 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Sun, 31 Jan 2016 11:57:41 +0100
+Subject: ALSA: rawmidi: Make snd_rawmidi_transmit() race-free
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 06ab30034ed9c200a570ab13c017bde248ddb2a6 upstream.
+
+A kernel WARNING in snd_rawmidi_transmit_ack() is triggered by
+syzkaller fuzzer:
+  WARNING: CPU: 1 PID: 20739 at sound/core/rawmidi.c:1136
+Call Trace:
+ [<     inline     >] __dump_stack lib/dump_stack.c:15
+ [<ffffffff82999e2d>] dump_stack+0x6f/0xa2 lib/dump_stack.c:50
+ [<ffffffff81352089>] warn_slowpath_common+0xd9/0x140 kernel/panic.c:482
+ [<ffffffff813522b9>] warn_slowpath_null+0x29/0x30 kernel/panic.c:515
+ [<ffffffff84f80bd5>] snd_rawmidi_transmit_ack+0x275/0x400 sound/core/rawmidi.c:1136
+ [<ffffffff84fdb3c1>] snd_virmidi_output_trigger+0x4b1/0x5a0 sound/core/seq/seq_virmidi.c:163
+ [<     inline     >] snd_rawmidi_output_trigger sound/core/rawmidi.c:150
+ [<ffffffff84f87ed9>] snd_rawmidi_kernel_write1+0x549/0x780 sound/core/rawmidi.c:1223
+ [<ffffffff84f89fd3>] snd_rawmidi_write+0x543/0xb30 sound/core/rawmidi.c:1273
+ [<ffffffff817b0323>] __vfs_write+0x113/0x480 fs/read_write.c:528
+ [<ffffffff817b1db7>] vfs_write+0x167/0x4a0 fs/read_write.c:577
+ [<     inline     >] SYSC_write fs/read_write.c:624
+ [<ffffffff817b50a1>] SyS_write+0x111/0x220 fs/read_write.c:616
+ [<ffffffff86336c36>] entry_SYSCALL_64_fastpath+0x16/0x7a arch/x86/entry/entry_64.S:185
+
+Also a similar warning is found but in another path:
+Call Trace:
+ [<     inline     >] __dump_stack lib/dump_stack.c:15
+ [<ffffffff82be2c0d>] dump_stack+0x6f/0xa2 lib/dump_stack.c:50
+ [<ffffffff81355139>] warn_slowpath_common+0xd9/0x140 kernel/panic.c:482
+ [<ffffffff81355369>] warn_slowpath_null+0x29/0x30 kernel/panic.c:515
+ [<ffffffff8527e69a>] rawmidi_transmit_ack+0x24a/0x3b0 sound/core/rawmidi.c:1133
+ [<ffffffff8527e851>] snd_rawmidi_transmit_ack+0x51/0x80 sound/core/rawmidi.c:1163
+ [<ffffffff852d9046>] snd_virmidi_output_trigger+0x2b6/0x570 sound/core/seq/seq_virmidi.c:185
+ [<     inline     >] snd_rawmidi_output_trigger sound/core/rawmidi.c:150
+ [<ffffffff85285a0b>] snd_rawmidi_kernel_write1+0x4bb/0x760 sound/core/rawmidi.c:1252
+ [<ffffffff85287b73>] snd_rawmidi_write+0x543/0xb30 sound/core/rawmidi.c:1302
+ [<ffffffff817ba5f3>] __vfs_write+0x113/0x480 fs/read_write.c:528
+ [<ffffffff817bc087>] vfs_write+0x167/0x4a0 fs/read_write.c:577
+ [<     inline     >] SYSC_write fs/read_write.c:624
+ [<ffffffff817bf371>] SyS_write+0x111/0x220 fs/read_write.c:616
+ [<ffffffff86660276>] entry_SYSCALL_64_fastpath+0x16/0x7a arch/x86/entry/entry_64.S:185
+
+In the former case, the reason is that virmidi has an open code
+calling snd_rawmidi_transmit_ack() with the value calculated outside
+the spinlock.   We may use snd_rawmidi_transmit() in a loop just for
+consuming the input data, but even there, there is a race between
+snd_rawmidi_transmit_peek() and snd_rawmidi_tranmit_ack().
+
+Similarly in the latter case, it calls snd_rawmidi_transmit_peek() and
+snd_rawmidi_tranmit_ack() separately without protection, so they are
+racy as well.
+
+The patch tries to address these issues by the following ways:
+- Introduce the unlocked versions of snd_rawmidi_transmit_peek() and
+  snd_rawmidi_transmit_ack() to be called inside the explicit lock.
+- Rewrite snd_rawmidi_transmit() to be race-free (the former case).
+- Make the split calls (the latter case) protected in the rawmidi spin
+  lock.
+
+BugLink: http://lkml.kernel.org/r/CACT4Y+YPq1+cYLkadwjWa5XjzF1_Vki1eHnVn-Lm0hzhSpu5PA@mail.gmail.com
+BugLink: http://lkml.kernel.org/r/CACT4Y+acG4iyphdOZx47Nyq_VHGbpJQK-6xNpiqUjaZYqsXOGw@mail.gmail.com
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Tested-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/sound/rawmidi.h      |    4 +
+ sound/core/rawmidi.c         |   98 +++++++++++++++++++++++++++++++------------
+ sound/core/seq/seq_virmidi.c |   17 +++++--
+ 3 files changed, 88 insertions(+), 31 deletions(-)
+
+--- a/include/sound/rawmidi.h
++++ b/include/sound/rawmidi.h
+@@ -167,6 +167,10 @@ int snd_rawmidi_transmit_peek(struct snd
+ int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count);
+ int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,
+                        unsigned char *buffer, int count);
++int __snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
++                            unsigned char *buffer, int count);
++int __snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream,
++                             int count);
+ /* main midi functions */
+--- a/sound/core/rawmidi.c
++++ b/sound/core/rawmidi.c
+@@ -1055,23 +1055,16 @@ int snd_rawmidi_transmit_empty(struct sn
+ EXPORT_SYMBOL(snd_rawmidi_transmit_empty);
+ /**
+- * snd_rawmidi_transmit_peek - copy data from the internal buffer
++ * __snd_rawmidi_transmit_peek - copy data from the internal buffer
+  * @substream: the rawmidi substream
+  * @buffer: the buffer pointer
+  * @count: data size to transfer
+  *
+- * Copies data from the internal output buffer to the given buffer.
+- *
+- * Call this in the interrupt handler when the midi output is ready,
+- * and call snd_rawmidi_transmit_ack() after the transmission is
+- * finished.
+- *
+- * Return: The size of copied data, or a negative error code on failure.
++ * This is a variant of snd_rawmidi_transmit_peek() without spinlock.
+  */
+-int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
++int __snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
+                             unsigned char *buffer, int count)
+ {
+-      unsigned long flags;
+       int result, count1;
+       struct snd_rawmidi_runtime *runtime = substream->runtime;
+@@ -1081,7 +1074,6 @@ int snd_rawmidi_transmit_peek(struct snd
+               return -EINVAL;
+       }
+       result = 0;
+-      spin_lock_irqsave(&runtime->lock, flags);
+       if (runtime->avail >= runtime->buffer_size) {
+               /* warning: lowlevel layer MUST trigger down the hardware */
+               goto __skip;
+@@ -1106,25 +1098,47 @@ int snd_rawmidi_transmit_peek(struct snd
+               }
+       }
+       __skip:
++      return result;
++}
++EXPORT_SYMBOL(__snd_rawmidi_transmit_peek);
++
++/**
++ * snd_rawmidi_transmit_peek - copy data from the internal buffer
++ * @substream: the rawmidi substream
++ * @buffer: the buffer pointer
++ * @count: data size to transfer
++ *
++ * Copies data from the internal output buffer to the given buffer.
++ *
++ * Call this in the interrupt handler when the midi output is ready,
++ * and call snd_rawmidi_transmit_ack() after the transmission is
++ * finished.
++ *
++ * Return: The size of copied data, or a negative error code on failure.
++ */
++int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
++                            unsigned char *buffer, int count)
++{
++      struct snd_rawmidi_runtime *runtime = substream->runtime;
++      int result;
++      unsigned long flags;
++
++      spin_lock_irqsave(&runtime->lock, flags);
++      result = __snd_rawmidi_transmit_peek(substream, buffer, count);
+       spin_unlock_irqrestore(&runtime->lock, flags);
+       return result;
+ }
+ EXPORT_SYMBOL(snd_rawmidi_transmit_peek);
+ /**
+- * snd_rawmidi_transmit_ack - acknowledge the transmission
++ * __snd_rawmidi_transmit_ack - acknowledge the transmission
+  * @substream: the rawmidi substream
+  * @count: the transferred count
+  *
+- * Advances the hardware pointer for the internal output buffer with
+- * the given size and updates the condition.
+- * Call after the transmission is finished.
+- *
+- * Return: The advanced size if successful, or a negative error code on failure.
++ * This is a variant of __snd_rawmidi_transmit_ack() without spinlock.
+  */
+-int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
++int __snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
+ {
+-      unsigned long flags;
+       struct snd_rawmidi_runtime *runtime = substream->runtime;
+       if (runtime->buffer == NULL) {
+@@ -1132,7 +1146,6 @@ int snd_rawmidi_transmit_ack(struct snd_
+                         "snd_rawmidi_transmit_ack: output is not active!!!\n");
+               return -EINVAL;
+       }
+-      spin_lock_irqsave(&runtime->lock, flags);
+       snd_BUG_ON(runtime->avail + count > runtime->buffer_size);
+       runtime->hw_ptr += count;
+       runtime->hw_ptr %= runtime->buffer_size;
+@@ -1142,9 +1155,32 @@ int snd_rawmidi_transmit_ack(struct snd_
+               if (runtime->drain || snd_rawmidi_ready(substream))
+                       wake_up(&runtime->sleep);
+       }
+-      spin_unlock_irqrestore(&runtime->lock, flags);
+       return count;
+ }
++EXPORT_SYMBOL(__snd_rawmidi_transmit_ack);
++
++/**
++ * snd_rawmidi_transmit_ack - acknowledge the transmission
++ * @substream: the rawmidi substream
++ * @count: the transferred count
++ *
++ * Advances the hardware pointer for the internal output buffer with
++ * the given size and updates the condition.
++ * Call after the transmission is finished.
++ *
++ * Return: The advanced size if successful, or a negative error code on failure.
++ */
++int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
++{
++      struct snd_rawmidi_runtime *runtime = substream->runtime;
++      int result;
++      unsigned long flags;
++
++      spin_lock_irqsave(&runtime->lock, flags);
++      result = __snd_rawmidi_transmit_ack(substream, count);
++      spin_unlock_irqrestore(&runtime->lock, flags);
++      return result;
++}
+ EXPORT_SYMBOL(snd_rawmidi_transmit_ack);
+ /**
+@@ -1160,12 +1196,22 @@ EXPORT_SYMBOL(snd_rawmidi_transmit_ack);
+ int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,
+                        unsigned char *buffer, int count)
+ {
++      struct snd_rawmidi_runtime *runtime = substream->runtime;
++      int result;
++      unsigned long flags;
++
++      spin_lock_irqsave(&runtime->lock, flags);
+       if (!substream->opened)
+-              return -EBADFD;
+-      count = snd_rawmidi_transmit_peek(substream, buffer, count);
+-      if (count < 0)
+-              return count;
+-      return snd_rawmidi_transmit_ack(substream, count);
++              result = -EBADFD;
++      else {
++              count = __snd_rawmidi_transmit_peek(substream, buffer, count);
++              if (count <= 0)
++                      result = count;
++              else
++                      result = __snd_rawmidi_transmit_ack(substream, count);
++      }
++      spin_unlock_irqrestore(&runtime->lock, flags);
++      return result;
+ }
+ EXPORT_SYMBOL(snd_rawmidi_transmit);
+--- a/sound/core/seq/seq_virmidi.c
++++ b/sound/core/seq/seq_virmidi.c
+@@ -155,21 +155,26 @@ static void snd_virmidi_output_trigger(s
+       struct snd_virmidi *vmidi = substream->runtime->private_data;
+       int count, res;
+       unsigned char buf[32], *pbuf;
++      unsigned long flags;
+       if (up) {
+               vmidi->trigger = 1;
+               if (vmidi->seq_mode == SNDRV_VIRMIDI_SEQ_DISPATCH &&
+                   !(vmidi->rdev->flags & SNDRV_VIRMIDI_SUBSCRIBE)) {
+-                      snd_rawmidi_transmit_ack(substream, substream->runtime->buffer_size - substream->runtime->avail);
+-                      return;         /* ignored */
++                      while (snd_rawmidi_transmit(substream, buf,
++                                                  sizeof(buf)) > 0) {
++                              /* ignored */
++                      }
++                      return;
+               }
+               if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) {
+                       if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, in_atomic(), 0) < 0)
+                               return;
+                       vmidi->event.type = SNDRV_SEQ_EVENT_NONE;
+               }
++              spin_lock_irqsave(&substream->runtime->lock, flags);
+               while (1) {
+-                      count = snd_rawmidi_transmit_peek(substream, buf, sizeof(buf));
++                      count = __snd_rawmidi_transmit_peek(substream, buf, sizeof(buf));
+                       if (count <= 0)
+                               break;
+                       pbuf = buf;
+@@ -179,16 +184,18 @@ static void snd_virmidi_output_trigger(s
+                                       snd_midi_event_reset_encode(vmidi->parser);
+                                       continue;
+                               }
+-                              snd_rawmidi_transmit_ack(substream, res);
++                              __snd_rawmidi_transmit_ack(substream, res);
+                               pbuf += res;
+                               count -= res;
+                               if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) {
+                                       if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, in_atomic(), 0) < 0)
+-                                              return;
++                                              goto out;
+                                       vmidi->event.type = SNDRV_SEQ_EVENT_NONE;
+                               }
+                       }
+               }
++      out:
++              spin_unlock_irqrestore(&substream->runtime->lock, flags);
+       } else {
+               vmidi->trigger = 0;
+       }
diff --git a/queue-4.3/alsa-rawmidi-remove-kernel-warning-for-null-user-space-buffer-check.patch b/queue-4.3/alsa-rawmidi-remove-kernel-warning-for-null-user-space-buffer-check.patch
new file mode 100644 (file)
index 0000000..3ede9f0
--- /dev/null
@@ -0,0 +1,33 @@
+From cc85f7a634cfaf9f0713c6aa06d08817424db37a Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 1 Feb 2016 12:04:55 +0100
+Subject: ALSA: rawmidi: Remove kernel WARNING for NULL user-space buffer check
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit cc85f7a634cfaf9f0713c6aa06d08817424db37a upstream.
+
+NULL user-space buffer can be passed even in a normal path, thus it's
+not good to spew a kernel warning with stack trace at each time.
+Just drop snd_BUG_ON() macro usage there.
+
+BugLink: http://lkml.kernel.org/r/CACT4Y+YfVJ3L+q0i-4vyQVyyPD7V=OMX0PWPi29x9Bo3QaBLdw@mail.gmail.com
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/rawmidi.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sound/core/rawmidi.c
++++ b/sound/core/rawmidi.c
+@@ -1224,7 +1224,7 @@ static long snd_rawmidi_kernel_write1(st
+       long count1, result;
+       struct snd_rawmidi_runtime *runtime = substream->runtime;
+-      if (snd_BUG_ON(!kernelbuf && !userbuf))
++      if (!kernelbuf && !userbuf)
+               return -EINVAL;
+       if (snd_BUG_ON(!runtime->buffer))
+               return -EINVAL;
diff --git a/queue-4.3/alsa-seq-degrade-the-error-message-for-too-many-opens.patch b/queue-4.3/alsa-seq-degrade-the-error-message-for-too-many-opens.patch
new file mode 100644 (file)
index 0000000..7bd41f9
--- /dev/null
@@ -0,0 +1,34 @@
+From da10816e3d923565b470fec78a674baba794ed33 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 25 Jan 2016 11:24:56 +0100
+Subject: ALSA: seq: Degrade the error message for too many opens
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit da10816e3d923565b470fec78a674baba794ed33 upstream.
+
+ALSA OSS sequencer spews a kernel error message ("ALSA: seq_oss: too
+many applications") when user-space tries to open more than the
+limit.  This means that it can easily fill the log buffer.
+
+Since it's merely a normal error, it's safe to suppress it via
+pr_debug() instead.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/seq/oss/seq_oss_init.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sound/core/seq/oss/seq_oss_init.c
++++ b/sound/core/seq/oss/seq_oss_init.c
+@@ -202,7 +202,7 @@ snd_seq_oss_open(struct file *file, int
+       dp->index = i;
+       if (i >= SNDRV_SEQ_OSS_MAX_CLIENTS) {
+-              pr_err("ALSA: seq_oss: too many applications\n");
++              pr_debug("ALSA: seq_oss: too many applications\n");
+               rc = -ENOMEM;
+               goto _error;
+       }
diff --git a/queue-4.3/alsa-seq-fix-incorrect-sanity-check-at-snd_seq_oss_synth_cleanup.patch b/queue-4.3/alsa-seq-fix-incorrect-sanity-check-at-snd_seq_oss_synth_cleanup.patch
new file mode 100644 (file)
index 0000000..7ecb9c1
--- /dev/null
@@ -0,0 +1,35 @@
+From 599151336638d57b98d92338aa59c048e3a3e97d Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 25 Jan 2016 11:01:47 +0100
+Subject: ALSA: seq: Fix incorrect sanity check at snd_seq_oss_synth_cleanup()
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 599151336638d57b98d92338aa59c048e3a3e97d upstream.
+
+ALSA sequencer OSS emulation code has a sanity check for currently
+opened devices, but there is a thinko there, eventually it spews
+warnings and skips the operation wrongly like:
+  WARNING: CPU: 1 PID: 7573 at sound/core/seq/oss/seq_oss_synth.c:311
+
+Fix this off-by-one error.
+
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/seq/oss/seq_oss_synth.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sound/core/seq/oss/seq_oss_synth.c
++++ b/sound/core/seq/oss/seq_oss_synth.c
+@@ -308,7 +308,7 @@ snd_seq_oss_synth_cleanup(struct seq_oss
+       struct seq_oss_synth *rec;
+       struct seq_oss_synthinfo *info;
+-      if (snd_BUG_ON(dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS))
++      if (snd_BUG_ON(dp->max_synthdev > SNDRV_SEQ_OSS_MAX_SYNTH_DEVS))
+               return;
+       for (i = 0; i < dp->max_synthdev; i++) {
+               info = &dp->synths[i];
diff --git a/queue-4.3/alsa-seq-fix-lockdep-warnings-due-to-double-mutex-locks.patch b/queue-4.3/alsa-seq-fix-lockdep-warnings-due-to-double-mutex-locks.patch
new file mode 100644 (file)
index 0000000..e62655c
--- /dev/null
@@ -0,0 +1,377 @@
+From 7f0973e973cd74aa40747c9d38844560cd184ee8 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 3 Feb 2016 08:32:44 +0100
+Subject: ALSA: seq: Fix lockdep warnings due to double mutex locks
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 7f0973e973cd74aa40747c9d38844560cd184ee8 upstream.
+
+The port subscription code uses double mutex locks for source and
+destination ports, and this may become racy once when wrongly set up.
+It leads to lockdep warning splat, typically triggered by fuzzer like
+syzkaller, although the actual deadlock hasn't been seen, so far.
+
+This patch simplifies the handling by reducing to two single locks, so
+that no lockdep warning will be trigger any longer.
+
+By splitting to two actions, a still-in-progress element shall be
+added in one list while handling another.  For ignoring this element,
+a new check is added in deliver_to_subscribers().
+
+Along with it, the code to add/remove the subscribers list element was
+cleaned up and refactored.
+
+BugLink: http://lkml.kernel.org/r/CACT4Y+aKQXV7xkBW9hpQbzaDO7LrUvohxWh-UwMxXjDy-yBD=A@mail.gmail.com
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Tested-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/seq/seq_clientmgr.c |    3 
+ sound/core/seq/seq_ports.c     |  235 ++++++++++++++++++++++-------------------
+ 2 files changed, 134 insertions(+), 104 deletions(-)
+
+--- a/sound/core/seq/seq_clientmgr.c
++++ b/sound/core/seq/seq_clientmgr.c
+@@ -678,6 +678,9 @@ static int deliver_to_subscribers(struct
+       else
+               down_read(&grp->list_mutex);
+       list_for_each_entry(subs, &grp->list_head, src_list) {
++              /* both ports ready? */
++              if (atomic_read(&subs->ref_count) != 2)
++                      continue;
+               event->dest = subs->info.dest;
+               if (subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP)
+                       /* convert time according to flag with subscription */
+--- a/sound/core/seq/seq_ports.c
++++ b/sound/core/seq/seq_ports.c
+@@ -173,10 +173,6 @@ struct snd_seq_client_port *snd_seq_crea
+ }
+ /* */
+-enum group_type {
+-      SRC_LIST, DEST_LIST
+-};
+-
+ static int subscribe_port(struct snd_seq_client *client,
+                         struct snd_seq_client_port *port,
+                         struct snd_seq_port_subs_info *grp,
+@@ -203,6 +199,20 @@ static struct snd_seq_client_port *get_c
+       return NULL;
+ }
++static void delete_and_unsubscribe_port(struct snd_seq_client *client,
++                                      struct snd_seq_client_port *port,
++                                      struct snd_seq_subscribers *subs,
++                                      bool is_src, bool ack);
++
++static inline struct snd_seq_subscribers *
++get_subscriber(struct list_head *p, bool is_src)
++{
++      if (is_src)
++              return list_entry(p, struct snd_seq_subscribers, src_list);
++      else
++              return list_entry(p, struct snd_seq_subscribers, dest_list);
++}
++
+ /*
+  * remove all subscribers on the list
+  * this is called from port_delete, for each src and dest list.
+@@ -210,7 +220,7 @@ static struct snd_seq_client_port *get_c
+ static void clear_subscriber_list(struct snd_seq_client *client,
+                                 struct snd_seq_client_port *port,
+                                 struct snd_seq_port_subs_info *grp,
+-                                int grptype)
++                                int is_src)
+ {
+       struct list_head *p, *n;
+@@ -219,15 +229,13 @@ static void clear_subscriber_list(struct
+               struct snd_seq_client *c;
+               struct snd_seq_client_port *aport;
+-              if (grptype == SRC_LIST) {
+-                      subs = list_entry(p, struct snd_seq_subscribers, src_list);
++              subs = get_subscriber(p, is_src);
++              if (is_src)
+                       aport = get_client_port(&subs->info.dest, &c);
+-              } else {
+-                      subs = list_entry(p, struct snd_seq_subscribers, dest_list);
++              else
+                       aport = get_client_port(&subs->info.sender, &c);
+-              }
+-              list_del(p);
+-              unsubscribe_port(client, port, grp, &subs->info, 0);
++              delete_and_unsubscribe_port(client, port, subs, is_src, false);
++
+               if (!aport) {
+                       /* looks like the connected port is being deleted.
+                        * we decrease the counter, and when both ports are deleted
+@@ -235,21 +243,14 @@ static void clear_subscriber_list(struct
+                        */
+                       if (atomic_dec_and_test(&subs->ref_count))
+                               kfree(subs);
+-              } else {
+-                      /* ok we got the connected port */
+-                      struct snd_seq_port_subs_info *agrp;
+-                      agrp = (grptype == SRC_LIST) ? &aport->c_dest : &aport->c_src;
+-                      down_write(&agrp->list_mutex);
+-                      if (grptype == SRC_LIST)
+-                              list_del(&subs->dest_list);
+-                      else
+-                              list_del(&subs->src_list);
+-                      up_write(&agrp->list_mutex);
+-                      unsubscribe_port(c, aport, agrp, &subs->info, 1);
+-                      kfree(subs);
+-                      snd_seq_port_unlock(aport);
+-                      snd_seq_client_unlock(c);
++                      continue;
+               }
++
++              /* ok we got the connected port */
++              delete_and_unsubscribe_port(c, aport, subs, !is_src, true);
++              kfree(subs);
++              snd_seq_port_unlock(aport);
++              snd_seq_client_unlock(c);
+       }
+ }
+@@ -262,8 +263,8 @@ static int port_delete(struct snd_seq_cl
+       snd_use_lock_sync(&port->use_lock); 
+       /* clear subscribers info */
+-      clear_subscriber_list(client, port, &port->c_src, SRC_LIST);
+-      clear_subscriber_list(client, port, &port->c_dest, DEST_LIST);
++      clear_subscriber_list(client, port, &port->c_src, true);
++      clear_subscriber_list(client, port, &port->c_dest, false);
+       if (port->private_free)
+               port->private_free(port->private_data);
+@@ -479,85 +480,120 @@ static int match_subs_info(struct snd_se
+       return 0;
+ }
++static int check_and_subscribe_port(struct snd_seq_client *client,
++                                  struct snd_seq_client_port *port,
++                                  struct snd_seq_subscribers *subs,
++                                  bool is_src, bool exclusive, bool ack)
++{
++      struct snd_seq_port_subs_info *grp;
++      struct list_head *p;
++      struct snd_seq_subscribers *s;
++      int err;
+-/* connect two ports */
+-int snd_seq_port_connect(struct snd_seq_client *connector,
+-                       struct snd_seq_client *src_client,
+-                       struct snd_seq_client_port *src_port,
+-                       struct snd_seq_client *dest_client,
+-                       struct snd_seq_client_port *dest_port,
+-                       struct snd_seq_port_subscribe *info)
+-{
+-      struct snd_seq_port_subs_info *src = &src_port->c_src;
+-      struct snd_seq_port_subs_info *dest = &dest_port->c_dest;
+-      struct snd_seq_subscribers *subs, *s;
+-      int err, src_called = 0;
+-      unsigned long flags;
+-      int exclusive;
+-
+-      subs = kzalloc(sizeof(*subs), GFP_KERNEL);
+-      if (! subs)
+-              return -ENOMEM;
+-
+-      subs->info = *info;
+-      atomic_set(&subs->ref_count, 2);
+-
+-      down_write(&src->list_mutex);
+-      down_write_nested(&dest->list_mutex, SINGLE_DEPTH_NESTING);
+-
+-      exclusive = info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE ? 1 : 0;
++      grp = is_src ? &port->c_src : &port->c_dest;
+       err = -EBUSY;
++      down_write(&grp->list_mutex);
+       if (exclusive) {
+-              if (! list_empty(&src->list_head) || ! list_empty(&dest->list_head))
++              if (!list_empty(&grp->list_head))
+                       goto __error;
+       } else {
+-              if (src->exclusive || dest->exclusive)
++              if (grp->exclusive)
+                       goto __error;
+               /* check whether already exists */
+-              list_for_each_entry(s, &src->list_head, src_list) {
+-                      if (match_subs_info(info, &s->info))
+-                              goto __error;
+-              }
+-              list_for_each_entry(s, &dest->list_head, dest_list) {
+-                      if (match_subs_info(info, &s->info))
++              list_for_each(p, &grp->list_head) {
++                      s = get_subscriber(p, is_src);
++                      if (match_subs_info(&subs->info, &s->info))
+                               goto __error;
+               }
+       }
+-      if ((err = subscribe_port(src_client, src_port, src, info,
+-                                connector->number != src_client->number)) < 0)
+-              goto __error;
+-      src_called = 1;
+-
+-      if ((err = subscribe_port(dest_client, dest_port, dest, info,
+-                                connector->number != dest_client->number)) < 0)
++      err = subscribe_port(client, port, grp, &subs->info, ack);
++      if (err < 0) {
++              grp->exclusive = 0;
+               goto __error;
++      }
+       /* add to list */
+-      write_lock_irqsave(&src->list_lock, flags);
+-      // write_lock(&dest->list_lock); // no other lock yet
+-      list_add_tail(&subs->src_list, &src->list_head);
+-      list_add_tail(&subs->dest_list, &dest->list_head);
+-      // write_unlock(&dest->list_lock); // no other lock yet
+-      write_unlock_irqrestore(&src->list_lock, flags);
++      write_lock_irq(&grp->list_lock);
++      if (is_src)
++              list_add_tail(&subs->src_list, &grp->list_head);
++      else
++              list_add_tail(&subs->dest_list, &grp->list_head);
++      grp->exclusive = exclusive;
++      atomic_inc(&subs->ref_count);
++      write_unlock_irq(&grp->list_lock);
++      err = 0;
+-      src->exclusive = dest->exclusive = exclusive;
++ __error:
++      up_write(&grp->list_mutex);
++      return err;
++}
++
++static void delete_and_unsubscribe_port(struct snd_seq_client *client,
++                                      struct snd_seq_client_port *port,
++                                      struct snd_seq_subscribers *subs,
++                                      bool is_src, bool ack)
++{
++      struct snd_seq_port_subs_info *grp;
++
++      grp = is_src ? &port->c_src : &port->c_dest;
++      down_write(&grp->list_mutex);
++      write_lock_irq(&grp->list_lock);
++      if (is_src)
++              list_del(&subs->src_list);
++      else
++              list_del(&subs->dest_list);
++      grp->exclusive = 0;
++      write_unlock_irq(&grp->list_lock);
++      up_write(&grp->list_mutex);
++
++      unsubscribe_port(client, port, grp, &subs->info, ack);
++}
++
++/* connect two ports */
++int snd_seq_port_connect(struct snd_seq_client *connector,
++                       struct snd_seq_client *src_client,
++                       struct snd_seq_client_port *src_port,
++                       struct snd_seq_client *dest_client,
++                       struct snd_seq_client_port *dest_port,
++                       struct snd_seq_port_subscribe *info)
++{
++      struct snd_seq_subscribers *subs;
++      bool exclusive;
++      int err;
++
++      subs = kzalloc(sizeof(*subs), GFP_KERNEL);
++      if (!subs)
++              return -ENOMEM;
++
++      subs->info = *info;
++      atomic_set(&subs->ref_count, 0);
++      INIT_LIST_HEAD(&subs->src_list);
++      INIT_LIST_HEAD(&subs->dest_list);
++
++      exclusive = !!(info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE);
++
++      err = check_and_subscribe_port(src_client, src_port, subs, true,
++                                     exclusive,
++                                     connector->number != src_client->number);
++      if (err < 0)
++              goto error;
++      err = check_and_subscribe_port(dest_client, dest_port, subs, false,
++                                     exclusive,
++                                     connector->number != dest_client->number);
++      if (err < 0)
++              goto error_dest;
+-      up_write(&dest->list_mutex);
+-      up_write(&src->list_mutex);
+       return 0;
+- __error:
+-      if (src_called)
+-              unsubscribe_port(src_client, src_port, src, info,
+-                               connector->number != src_client->number);
++ error_dest:
++      delete_and_unsubscribe_port(src_client, src_port, subs, true,
++                                  connector->number != src_client->number);
++ error:
+       kfree(subs);
+-      up_write(&dest->list_mutex);
+-      up_write(&src->list_mutex);
+       return err;
+ }
+-
+ /* remove the connection */
+ int snd_seq_port_disconnect(struct snd_seq_client *connector,
+                           struct snd_seq_client *src_client,
+@@ -567,37 +603,28 @@ int snd_seq_port_disconnect(struct snd_s
+                           struct snd_seq_port_subscribe *info)
+ {
+       struct snd_seq_port_subs_info *src = &src_port->c_src;
+-      struct snd_seq_port_subs_info *dest = &dest_port->c_dest;
+       struct snd_seq_subscribers *subs;
+       int err = -ENOENT;
+-      unsigned long flags;
+       down_write(&src->list_mutex);
+-      down_write_nested(&dest->list_mutex, SINGLE_DEPTH_NESTING);
+-
+       /* look for the connection */
+       list_for_each_entry(subs, &src->list_head, src_list) {
+               if (match_subs_info(info, &subs->info)) {
+-                      write_lock_irqsave(&src->list_lock, flags);
+-                      // write_lock(&dest->list_lock);  // no lock yet
+-                      list_del(&subs->src_list);
+-                      list_del(&subs->dest_list);
+-                      // write_unlock(&dest->list_lock);
+-                      write_unlock_irqrestore(&src->list_lock, flags);
+-                      src->exclusive = dest->exclusive = 0;
+-                      unsubscribe_port(src_client, src_port, src, info,
+-                                       connector->number != src_client->number);
+-                      unsubscribe_port(dest_client, dest_port, dest, info,
+-                                       connector->number != dest_client->number);
+-                      kfree(subs);
++                      atomic_dec(&subs->ref_count); /* mark as not ready */
+                       err = 0;
+                       break;
+               }
+       }
+-
+-      up_write(&dest->list_mutex);
+       up_write(&src->list_mutex);
+-      return err;
++      if (err < 0)
++              return err;
++
++      delete_and_unsubscribe_port(src_client, src_port, subs, true,
++                                  connector->number != src_client->number);
++      delete_and_unsubscribe_port(dest_client, dest_port, subs, false,
++                                  connector->number != dest_client->number);
++      kfree(subs);
++      return 0;
+ }
diff --git a/queue-4.3/alsa-seq-fix-race-at-closing-in-virmidi-driver.patch b/queue-4.3/alsa-seq-fix-race-at-closing-in-virmidi-driver.patch
new file mode 100644 (file)
index 0000000..04c7a78
--- /dev/null
@@ -0,0 +1,43 @@
+From 2d1b5c08366acd46c35a2e9aba5d650cb5bf5c19 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 1 Feb 2016 12:06:42 +0100
+Subject: ALSA: seq: Fix race at closing in virmidi driver
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 2d1b5c08366acd46c35a2e9aba5d650cb5bf5c19 upstream.
+
+The virmidi driver has an open race at closing its assigned rawmidi
+device, and this may lead to use-after-free in
+snd_seq_deliver_single_event().
+
+Plug the hole by properly protecting the linked list deletion and
+calling in the right order in snd_virmidi_input_close().
+
+BugLink: http://lkml.kernel.org/r/CACT4Y+Zd66+w12fNN85-425cVQT=K23kWbhnCEcMB8s3us-Frw@mail.gmail.com
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Tested-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/seq/seq_virmidi.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/sound/core/seq/seq_virmidi.c
++++ b/sound/core/seq/seq_virmidi.c
+@@ -261,9 +261,13 @@ static int snd_virmidi_output_open(struc
+  */
+ static int snd_virmidi_input_close(struct snd_rawmidi_substream *substream)
+ {
++      struct snd_virmidi_dev *rdev = substream->rmidi->private_data;
+       struct snd_virmidi *vmidi = substream->runtime->private_data;
+-      snd_midi_event_free(vmidi->parser);
++
++      write_lock_irq(&rdev->filelist_lock);
+       list_del(&vmidi->list);
++      write_unlock_irq(&rdev->filelist_lock);
++      snd_midi_event_free(vmidi->parser);
+       substream->runtime->private_data = NULL;
+       kfree(vmidi);
+       return 0;
diff --git a/queue-4.3/alsa-seq-fix-yet-another-races-among-alsa-timer-accesses.patch b/queue-4.3/alsa-seq-fix-yet-another-races-among-alsa-timer-accesses.patch
new file mode 100644 (file)
index 0000000..61bde13
--- /dev/null
@@ -0,0 +1,228 @@
+From 2cdc7b636d55cbcf42e1e6c8accd85e62d3e9ae8 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Sat, 30 Jan 2016 23:30:25 +0100
+Subject: ALSA: seq: Fix yet another races among ALSA timer accesses
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 2cdc7b636d55cbcf42e1e6c8accd85e62d3e9ae8 upstream.
+
+ALSA sequencer may open/close and control ALSA timer instance
+dynamically either via sequencer events or direct ioctls.  These are
+done mostly asynchronously, and it may call still some timer action
+like snd_timer_start() while another is calling snd_timer_close().
+Since the instance gets removed by snd_timer_close(), it may lead to
+a use-after-free.
+
+This patch tries to address such a race by protecting each
+snd_timer_*() call via the existing spinlock and also by avoiding the
+access to timer during close call.
+
+BugLink: http://lkml.kernel.org/r/CACT4Y+Z6RzW5MBr-HUdV-8zwg71WQfKTdPpYGvOeS7v4cyurNQ@mail.gmail.com
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/seq/seq_timer.c |   87 ++++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 67 insertions(+), 20 deletions(-)
+
+--- a/sound/core/seq/seq_timer.c
++++ b/sound/core/seq/seq_timer.c
+@@ -90,6 +90,9 @@ void snd_seq_timer_delete(struct snd_seq
+ void snd_seq_timer_defaults(struct snd_seq_timer * tmr)
+ {
++      unsigned long flags;
++
++      spin_lock_irqsave(&tmr->lock, flags);
+       /* setup defaults */
+       tmr->ppq = 96;          /* 96 PPQ */
+       tmr->tempo = 500000;    /* 120 BPM */
+@@ -105,21 +108,25 @@ void snd_seq_timer_defaults(struct snd_s
+       tmr->preferred_resolution = seq_default_timer_resolution;
+       tmr->skew = tmr->skew_base = SKEW_BASE;
++      spin_unlock_irqrestore(&tmr->lock, flags);
+ }
+-void snd_seq_timer_reset(struct snd_seq_timer * tmr)
++static void seq_timer_reset(struct snd_seq_timer *tmr)
+ {
+-      unsigned long flags;
+-
+-      spin_lock_irqsave(&tmr->lock, flags);
+-
+       /* reset time & songposition */
+       tmr->cur_time.tv_sec = 0;
+       tmr->cur_time.tv_nsec = 0;
+       tmr->tick.cur_tick = 0;
+       tmr->tick.fraction = 0;
++}
++
++void snd_seq_timer_reset(struct snd_seq_timer *tmr)
++{
++      unsigned long flags;
++      spin_lock_irqsave(&tmr->lock, flags);
++      seq_timer_reset(tmr);
+       spin_unlock_irqrestore(&tmr->lock, flags);
+ }
+@@ -138,8 +145,11 @@ static void snd_seq_timer_interrupt(stru
+       tmr = q->timer;
+       if (tmr == NULL)
+               return;
+-      if (!tmr->running)
++      spin_lock_irqsave(&tmr->lock, flags);
++      if (!tmr->running) {
++              spin_unlock_irqrestore(&tmr->lock, flags);
+               return;
++      }
+       resolution *= ticks;
+       if (tmr->skew != tmr->skew_base) {
+@@ -148,8 +158,6 @@ static void snd_seq_timer_interrupt(stru
+                       (((resolution & 0xffff) * tmr->skew) >> 16);
+       }
+-      spin_lock_irqsave(&tmr->lock, flags);
+-
+       /* update timer */
+       snd_seq_inc_time_nsec(&tmr->cur_time, resolution);
+@@ -296,26 +304,30 @@ int snd_seq_timer_open(struct snd_seq_qu
+       t->callback = snd_seq_timer_interrupt;
+       t->callback_data = q;
+       t->flags |= SNDRV_TIMER_IFLG_AUTO;
++      spin_lock_irq(&tmr->lock);
+       tmr->timeri = t;
++      spin_unlock_irq(&tmr->lock);
+       return 0;
+ }
+ int snd_seq_timer_close(struct snd_seq_queue *q)
+ {
+       struct snd_seq_timer *tmr;
++      struct snd_timer_instance *t;
+       
+       tmr = q->timer;
+       if (snd_BUG_ON(!tmr))
+               return -EINVAL;
+-      if (tmr->timeri) {
+-              snd_timer_stop(tmr->timeri);
+-              snd_timer_close(tmr->timeri);
+-              tmr->timeri = NULL;
+-      }
++      spin_lock_irq(&tmr->lock);
++      t = tmr->timeri;
++      tmr->timeri = NULL;
++      spin_unlock_irq(&tmr->lock);
++      if (t)
++              snd_timer_close(t);
+       return 0;
+ }
+-int snd_seq_timer_stop(struct snd_seq_timer * tmr)
++static int seq_timer_stop(struct snd_seq_timer *tmr)
+ {
+       if (! tmr->timeri)
+               return -EINVAL;
+@@ -326,6 +338,17 @@ int snd_seq_timer_stop(struct snd_seq_ti
+       return 0;
+ }
++int snd_seq_timer_stop(struct snd_seq_timer *tmr)
++{
++      unsigned long flags;
++      int err;
++
++      spin_lock_irqsave(&tmr->lock, flags);
++      err = seq_timer_stop(tmr);
++      spin_unlock_irqrestore(&tmr->lock, flags);
++      return err;
++}
++
+ static int initialize_timer(struct snd_seq_timer *tmr)
+ {
+       struct snd_timer *t;
+@@ -358,13 +381,13 @@ static int initialize_timer(struct snd_s
+       return 0;
+ }
+-int snd_seq_timer_start(struct snd_seq_timer * tmr)
++static int seq_timer_start(struct snd_seq_timer *tmr)
+ {
+       if (! tmr->timeri)
+               return -EINVAL;
+       if (tmr->running)
+-              snd_seq_timer_stop(tmr);
+-      snd_seq_timer_reset(tmr);
++              seq_timer_stop(tmr);
++      seq_timer_reset(tmr);
+       if (initialize_timer(tmr) < 0)
+               return -EINVAL;
+       snd_timer_start(tmr->timeri, tmr->ticks);
+@@ -373,14 +396,25 @@ int snd_seq_timer_start(struct snd_seq_t
+       return 0;
+ }
+-int snd_seq_timer_continue(struct snd_seq_timer * tmr)
++int snd_seq_timer_start(struct snd_seq_timer *tmr)
++{
++      unsigned long flags;
++      int err;
++
++      spin_lock_irqsave(&tmr->lock, flags);
++      err = seq_timer_start(tmr);
++      spin_unlock_irqrestore(&tmr->lock, flags);
++      return err;
++}
++
++static int seq_timer_continue(struct snd_seq_timer *tmr)
+ {
+       if (! tmr->timeri)
+               return -EINVAL;
+       if (tmr->running)
+               return -EBUSY;
+       if (! tmr->initialized) {
+-              snd_seq_timer_reset(tmr);
++              seq_timer_reset(tmr);
+               if (initialize_timer(tmr) < 0)
+                       return -EINVAL;
+       }
+@@ -390,11 +424,24 @@ int snd_seq_timer_continue(struct snd_se
+       return 0;
+ }
++int snd_seq_timer_continue(struct snd_seq_timer *tmr)
++{
++      unsigned long flags;
++      int err;
++
++      spin_lock_irqsave(&tmr->lock, flags);
++      err = seq_timer_continue(tmr);
++      spin_unlock_irqrestore(&tmr->lock, flags);
++      return err;
++}
++
+ /* return current 'real' time. use timeofday() to get better granularity. */
+ snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr)
+ {
+       snd_seq_real_time_t cur_time;
++      unsigned long flags;
++      spin_lock_irqsave(&tmr->lock, flags);
+       cur_time = tmr->cur_time;
+       if (tmr->running) { 
+               struct timeval tm;
+@@ -410,7 +457,7 @@ snd_seq_real_time_t snd_seq_timer_get_cu
+               }
+               snd_seq_sanity_real_time(&cur_time);
+       }
+-                
++      spin_unlock_irqrestore(&tmr->lock, flags);
+       return cur_time;        
+ }
diff --git a/queue-4.3/alsa-timer-fix-leftover-link-at-closing.patch b/queue-4.3/alsa-timer-fix-leftover-link-at-closing.patch
new file mode 100644 (file)
index 0000000..832847d
--- /dev/null
@@ -0,0 +1,46 @@
+From 094fd3be87b0f102589e2d5c3fa5d06b7e20496d Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Thu, 4 Feb 2016 17:06:13 +0100
+Subject: ALSA: timer: Fix leftover link at closing
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 094fd3be87b0f102589e2d5c3fa5d06b7e20496d upstream.
+
+In ALSA timer core, the active timer instance is managed in
+active_list linked list.  Each element is added / removed dynamically
+at timer start, stop and in timer interrupt.  The problem is that
+snd_timer_interrupt() has a thinko and leaves the element in
+active_list when it's the last opened element.  This eventually leads
+to list corruption or use-after-free error.
+
+This hasn't been revealed because we used to delete the list forcibly
+in snd_timer_stop() in the past.  However, the recent fix avoids the
+double-stop behavior (in commit [f784beb75ce8: ALSA: timer: Fix link
+corruption due to double start or stop]), and this leak hits reality.
+
+This patch fixes the link management in snd_timer_interrupt().  Now it
+simply unlinks no matter which stream is.
+
+BugLink: http://lkml.kernel.org/r/CACT4Y+Yy2aukHP-EDp8-ziNqNNmb-NTf=jDWXMP7jB8HDa2vng@mail.gmail.com
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/timer.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/sound/core/timer.c
++++ b/sound/core/timer.c
+@@ -724,8 +724,8 @@ void snd_timer_interrupt(struct snd_time
+                       ti->cticks = ti->ticks;
+               } else {
+                       ti->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
+-                      if (--timer->running)
+-                              list_del_init(&ti->active_list);
++                      --timer->running;
++                      list_del_init(&ti->active_list);
+               }
+               if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) ||
+                   (ti->flags & SNDRV_TIMER_IFLG_FAST))
diff --git a/queue-4.3/alsa-timer-fix-link-corruption-due-to-double-start-or-stop.patch b/queue-4.3/alsa-timer-fix-link-corruption-due-to-double-start-or-stop.patch
new file mode 100644 (file)
index 0000000..93352de
--- /dev/null
@@ -0,0 +1,112 @@
+From f784beb75ce82f4136f8a0960d3ee872f7109e09 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Sat, 30 Jan 2016 23:09:08 +0100
+Subject: ALSA: timer: Fix link corruption due to double start or stop
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit f784beb75ce82f4136f8a0960d3ee872f7109e09 upstream.
+
+Although ALSA timer code got hardening for races, it still causes
+use-after-free error.  This is however rather a corrupted linked list,
+not actually the concurrent accesses.  Namely, when timer start is
+triggered twice, list_add_tail() is called twice, too.  This ends
+up with the link corruption and triggers KASAN error.
+
+The simplest fix would be replacing list_add_tail() with
+list_move_tail(), but fundamentally it's the problem that we don't
+check the double start/stop correctly.  So, the right fix here is to
+add the proper checks to snd_timer_start() and snd_timer_stop() (and
+their variants).
+
+BugLink: http://lkml.kernel.org/r/CACT4Y+ZyPRoMQjmawbvmCEDrkBD2BQuH7R09=eOkf5ESK8kJAw@mail.gmail.com
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/timer.c |   30 ++++++++++++++++++++++++++++--
+ 1 file changed, 28 insertions(+), 2 deletions(-)
+
+--- a/sound/core/timer.c
++++ b/sound/core/timer.c
+@@ -452,6 +452,10 @@ static int snd_timer_start_slave(struct
+       unsigned long flags;
+       spin_lock_irqsave(&slave_active_lock, flags);
++      if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) {
++              spin_unlock_irqrestore(&slave_active_lock, flags);
++              return -EBUSY;
++      }
+       timeri->flags |= SNDRV_TIMER_IFLG_RUNNING;
+       if (timeri->master && timeri->timer) {
+               spin_lock(&timeri->timer->lock);
+@@ -476,7 +480,8 @@ int snd_timer_start(struct snd_timer_ins
+               return -EINVAL;
+       if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
+               result = snd_timer_start_slave(timeri);
+-              snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
++              if (result >= 0)
++                      snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
+               return result;
+       }
+       timer = timeri->timer;
+@@ -485,11 +490,18 @@ int snd_timer_start(struct snd_timer_ins
+       if (timer->card && timer->card->shutdown)
+               return -ENODEV;
+       spin_lock_irqsave(&timer->lock, flags);
++      if (timeri->flags & (SNDRV_TIMER_IFLG_RUNNING |
++                           SNDRV_TIMER_IFLG_START)) {
++              result = -EBUSY;
++              goto unlock;
++      }
+       timeri->ticks = timeri->cticks = ticks;
+       timeri->pticks = 0;
+       result = snd_timer_start1(timer, timeri, ticks);
++ unlock:
+       spin_unlock_irqrestore(&timer->lock, flags);
+-      snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
++      if (result >= 0)
++              snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
+       return result;
+ }
+@@ -505,6 +517,10 @@ static int _snd_timer_stop(struct snd_ti
+       if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
+               if (!keep_flag) {
+                       spin_lock_irqsave(&slave_active_lock, flags);
++                      if (!(timeri->flags & SNDRV_TIMER_IFLG_RUNNING)) {
++                              spin_unlock_irqrestore(&slave_active_lock, flags);
++                              return -EBUSY;
++                      }
+                       timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
+                       list_del_init(&timeri->ack_list);
+                       list_del_init(&timeri->active_list);
+@@ -516,6 +532,11 @@ static int _snd_timer_stop(struct snd_ti
+       if (!timer)
+               return -EINVAL;
+       spin_lock_irqsave(&timer->lock, flags);
++      if (!(timeri->flags & (SNDRV_TIMER_IFLG_RUNNING |
++                             SNDRV_TIMER_IFLG_START))) {
++              spin_unlock_irqrestore(&timer->lock, flags);
++              return -EBUSY;
++      }
+       list_del_init(&timeri->ack_list);
+       list_del_init(&timeri->active_list);
+       if (timer->card && timer->card->shutdown) {
+@@ -587,10 +608,15 @@ int snd_timer_continue(struct snd_timer_
+       if (timer->card && timer->card->shutdown)
+               return -ENODEV;
+       spin_lock_irqsave(&timer->lock, flags);
++      if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) {
++              result = -EBUSY;
++              goto unlock;
++      }
+       if (!timeri->cticks)
+               timeri->cticks = 1;
+       timeri->pticks = 0;
+       result = snd_timer_start1(timer, timeri, timer->sticks);
++ unlock:
+       spin_unlock_irqrestore(&timer->lock, flags);
+       snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_CONTINUE);
+       return result;
diff --git a/queue-4.3/alsa-timer-fix-race-at-concurrent-reads.patch b/queue-4.3/alsa-timer-fix-race-at-concurrent-reads.patch
new file mode 100644 (file)
index 0000000..b6085d3
--- /dev/null
@@ -0,0 +1,96 @@
+From 4dff5c7b7093b19c19d3a100f8a3ad87cb7cd9e7 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 8 Feb 2016 17:26:58 +0100
+Subject: ALSA: timer: Fix race at concurrent reads
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 4dff5c7b7093b19c19d3a100f8a3ad87cb7cd9e7 upstream.
+
+snd_timer_user_read() has a potential race among parallel reads, as
+qhead and qused are updated outside the critical section due to
+copy_to_user() calls.  Move them into the critical section, and also
+sanitize the relevant code a bit.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/timer.c |   34 +++++++++++++++-------------------
+ 1 file changed, 15 insertions(+), 19 deletions(-)
+
+--- a/sound/core/timer.c
++++ b/sound/core/timer.c
+@@ -1926,6 +1926,7 @@ static ssize_t snd_timer_user_read(struc
+ {
+       struct snd_timer_user *tu;
+       long result = 0, unit;
++      int qhead;
+       int err = 0;
+       tu = file->private_data;
+@@ -1937,7 +1938,7 @@ static ssize_t snd_timer_user_read(struc
+                       if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {
+                               err = -EAGAIN;
+-                              break;
++                              goto _error;
+                       }
+                       set_current_state(TASK_INTERRUPTIBLE);
+@@ -1952,42 +1953,37 @@ static ssize_t snd_timer_user_read(struc
+                       if (tu->disconnected) {
+                               err = -ENODEV;
+-                              break;
++                              goto _error;
+                       }
+                       if (signal_pending(current)) {
+                               err = -ERESTARTSYS;
+-                              break;
++                              goto _error;
+                       }
+               }
++              qhead = tu->qhead++;
++              tu->qhead %= tu->queue_size;
+               spin_unlock_irq(&tu->qlock);
+-              if (err < 0)
+-                      goto _error;
+               if (tu->tread) {
+-                      if (copy_to_user(buffer, &tu->tqueue[tu->qhead++],
+-                                       sizeof(struct snd_timer_tread))) {
++                      if (copy_to_user(buffer, &tu->tqueue[qhead],
++                                       sizeof(struct snd_timer_tread)))
+                               err = -EFAULT;
+-                              goto _error;
+-                      }
+               } else {
+-                      if (copy_to_user(buffer, &tu->queue[tu->qhead++],
+-                                       sizeof(struct snd_timer_read))) {
++                      if (copy_to_user(buffer, &tu->queue[qhead],
++                                       sizeof(struct snd_timer_read)))
+                               err = -EFAULT;
+-                              goto _error;
+-                      }
+               }
+-              tu->qhead %= tu->queue_size;
+-
+-              result += unit;
+-              buffer += unit;
+-
+               spin_lock_irq(&tu->qlock);
+               tu->qused--;
++              if (err < 0)
++                      goto _error;
++              result += unit;
++              buffer += unit;
+       }
+-      spin_unlock_irq(&tu->qlock);
+  _error:
++      spin_unlock_irq(&tu->qlock);
+       return result > 0 ? result : err;
+ }
diff --git a/queue-4.3/alsa-timer-fix-wrong-instance-passed-to-slave-callbacks.patch b/queue-4.3/alsa-timer-fix-wrong-instance-passed-to-slave-callbacks.patch
new file mode 100644 (file)
index 0000000..3321fca
--- /dev/null
@@ -0,0 +1,36 @@
+From 117159f0b9d392fb433a7871426fad50317f06f7 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 8 Feb 2016 17:36:25 +0100
+Subject: ALSA: timer: Fix wrong instance passed to slave callbacks
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 117159f0b9d392fb433a7871426fad50317f06f7 upstream.
+
+In snd_timer_notify1(), the wrong timer instance was passed for slave
+ccallback function.  This leads to the access to the wrong data when
+an incompatible master is handled (e.g. the master is the sequencer
+timer and the slave is a user timer), as spotted by syzkaller fuzzer.
+
+This patch fixes that wrong assignment.
+
+BugLink: http://lkml.kernel.org/r/CACT4Y+Y_Bm+7epAb=8Wi=AaWd+DYS7qawX52qxdCfOfY49vozQ@mail.gmail.com
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/timer.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sound/core/timer.c
++++ b/sound/core/timer.c
+@@ -423,7 +423,7 @@ static void snd_timer_notify1(struct snd
+       spin_lock_irqsave(&timer->lock, flags);
+       list_for_each_entry(ts, &ti->slave_active_head, active_list)
+               if (ts->ccallback)
+-                      ts->ccallback(ti, event + 100, &tstamp, resolution);
++                      ts->ccallback(ts, event + 100, &tstamp, resolution);
+       spin_unlock_irqrestore(&timer->lock, flags);
+ }
diff --git a/queue-4.3/alsa-usb-audio-add-native-dsd-support-for-ps-audio-nuwave-dac.patch b/queue-4.3/alsa-usb-audio-add-native-dsd-support-for-ps-audio-nuwave-dac.patch
new file mode 100644 (file)
index 0000000..9bd778b
--- /dev/null
@@ -0,0 +1,29 @@
+From ad678b4ccd41aa51cf5f142c0e8cffe9d61fc2bf Mon Sep 17 00:00:00 2001
+From: Jurgen Kramer <gtmkramer@xs4all.nl>
+Date: Fri, 29 Jan 2016 14:59:25 +0100
+Subject: ALSA: usb-audio: Add native DSD support for PS Audio NuWave DAC
+
+From: Jurgen Kramer <gtmkramer@xs4all.nl>
+
+commit ad678b4ccd41aa51cf5f142c0e8cffe9d61fc2bf upstream.
+
+This patch adds native DSD support for the PS Audio NuWave DAC.
+
+Signed-off-by: Jurgen Kramer <gtmkramer@xs4all.nl>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/usb/quirks.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -1288,6 +1288,7 @@ u64 snd_usb_interface_dsd_format_quirks(
+       case USB_ID(0x20b1, 0x2009): /* DIYINHK DSD DXD 384kHz USB to I2S/DSD */
+       case USB_ID(0x20b1, 0x2023): /* JLsounds I2SoverUSB */
+       case USB_ID(0x20b1, 0x3023): /* Aune X1S 32BIT/384 DSD DAC */
++      case USB_ID(0x2616, 0x0106): /* PS Audio NuWave DAC */
+               if (fp->altsetting == 3)
+                       return SNDRV_PCM_FMTBIT_DSD_U32_BE;
+               break;
diff --git a/queue-4.3/alsa-usb-audio-add-quirk-for-microsoft-lifecam-hd-6000.patch b/queue-4.3/alsa-usb-audio-add-quirk-for-microsoft-lifecam-hd-6000.patch
new file mode 100644 (file)
index 0000000..ce07551
--- /dev/null
@@ -0,0 +1,31 @@
+From 1b3c993a699bed282e47c3f7c49d539c331dae04 Mon Sep 17 00:00:00 2001
+From: Lev Lybin <lev.lybin@gmail.com>
+Date: Fri, 29 Jan 2016 22:55:11 +0700
+Subject: ALSA: usb-audio: Add quirk for Microsoft LifeCam HD-6000
+
+From: Lev Lybin <lev.lybin@gmail.com>
+
+commit 1b3c993a699bed282e47c3f7c49d539c331dae04 upstream.
+
+Microsoft LifeCam HD-6000 (045e:076f) requires the similar quirk for
+avoiding the stall due to the invalid sample rate reads.
+
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=111491
+Signed-off-by: Lev Lybin <lev.lybin@gmail.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/usb/quirks.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -1118,6 +1118,7 @@ bool snd_usb_get_sample_rate_quirk(struc
+       switch (chip->usb_id) {
+       case USB_ID(0x045E, 0x075D): /* MS Lifecam Cinema  */
+       case USB_ID(0x045E, 0x076D): /* MS Lifecam HD-5000 */
++      case USB_ID(0x045E, 0x076F): /* MS Lifecam HD-6000 */
+       case USB_ID(0x045E, 0x0772): /* MS Lifecam Studio */
+       case USB_ID(0x045E, 0x0779): /* MS Lifecam HD-3000 */
+       case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */
diff --git a/queue-4.3/alsa-usb-audio-avoid-freeing-umidi-object-twice.patch b/queue-4.3/alsa-usb-audio-avoid-freeing-umidi-object-twice.patch
new file mode 100644 (file)
index 0000000..8eaed02
--- /dev/null
@@ -0,0 +1,34 @@
+From 07d86ca93db7e5cdf4743564d98292042ec21af7 Mon Sep 17 00:00:00 2001
+From: Andrey Konovalov <andreyknvl@gmail.com>
+Date: Sat, 13 Feb 2016 11:08:06 +0300
+Subject: ALSA: usb-audio: avoid freeing umidi object twice
+
+From: Andrey Konovalov <andreyknvl@gmail.com>
+
+commit 07d86ca93db7e5cdf4743564d98292042ec21af7 upstream.
+
+The 'umidi' object will be free'd on the error path by snd_usbmidi_free()
+when tearing down the rawmidi interface. So we shouldn't try to free it
+in snd_usbmidi_create() after having registered the rawmidi interface.
+
+Found by KASAN.
+
+Signed-off-by: Andrey Konovalov <andreyknvl@gmail.com>
+Acked-by: Clemens Ladisch <clemens@ladisch.de>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/usb/midi.c |    1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/sound/usb/midi.c
++++ b/sound/usb/midi.c
+@@ -2451,7 +2451,6 @@ int snd_usbmidi_create(struct snd_card *
+       else
+               err = snd_usbmidi_create_endpoints(umidi, endpoints);
+       if (err < 0) {
+-              snd_usbmidi_free(umidi);
+               return err;
+       }
diff --git a/queue-4.3/alsa-usb-audio-fix-oppo-ha-1-vendor-id.patch b/queue-4.3/alsa-usb-audio-fix-oppo-ha-1-vendor-id.patch
new file mode 100644 (file)
index 0000000..3ec1143
--- /dev/null
@@ -0,0 +1,32 @@
+From 5327d6ba975042fd3da50ac6e94d1e9551ebeaec Mon Sep 17 00:00:00 2001
+From: Jurgen Kramer <gtmkramer@xs4all.nl>
+Date: Fri, 29 Jan 2016 14:49:55 +0100
+Subject: ALSA: usb-audio: Fix OPPO HA-1 vendor ID
+
+From: Jurgen Kramer <gtmkramer@xs4all.nl>
+
+commit 5327d6ba975042fd3da50ac6e94d1e9551ebeaec upstream.
+
+In my patch adding native DSD support for the Oppo HA-1, the wrong vendor ID got
+through. This patch fixes the vendor ID and aligns the comment.
+
+Fixes: a4eae3a506ea ('ALSA: usb: Add native DSD support for Oppo HA-1')
+Signed-off-by: Jurgen Kramer <gtmkramer@xs4all.nl>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/usb/quirks.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -1279,7 +1279,7 @@ u64 snd_usb_interface_dsd_format_quirks(
+       case USB_ID(0x20b1, 0x3008): /* iFi Audio micro/nano iDSD */
+       case USB_ID(0x20b1, 0x2008): /* Matrix Audio X-Sabre */
+       case USB_ID(0x20b1, 0x300a): /* Matrix Audio Mini-i Pro */
+-      case USB_ID(0x22d8, 0x0416): /* OPPO HA-1*/
++      case USB_ID(0x22d9, 0x0416): /* OPPO HA-1 */
+               if (fp->altsetting == 2)
+                       return SNDRV_PCM_FMTBIT_DSD_U32_BE;
+               break;
diff --git a/queue-4.3/alsa-usb-audio-fix-teac-ud-501-ud-503-nt-503-usb-delay.patch b/queue-4.3/alsa-usb-audio-fix-teac-ud-501-ud-503-nt-503-usb-delay.patch
new file mode 100644 (file)
index 0000000..4749f79
--- /dev/null
@@ -0,0 +1,53 @@
+From 5a4ff9ec8d6edd2ab1cfe8ce6a080d6e57cbea9a Mon Sep 17 00:00:00 2001
+From: Guillaume Fougnies <guillaume@eulerian.com>
+Date: Tue, 26 Jan 2016 00:28:27 +0100
+Subject: ALSA: usb-audio: Fix TEAC UD-501/UD-503/NT-503 usb delay
+
+From: Guillaume Fougnies <guillaume@eulerian.com>
+
+commit 5a4ff9ec8d6edd2ab1cfe8ce6a080d6e57cbea9a upstream.
+
+TEAC UD-501/UD-503/NT-503 fail to switch properly between different
+rate/format. Similar to 'Playback Design', this patch corrects the
+invalid clock source error for TEAC products and avoids complete
+freeze of the usb interface of 503 series.
+
+Signed-off-by: Guillaume Fougnies <guillaume@eulerian.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/usb/quirks.c |   14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -1202,8 +1202,12 @@ void snd_usb_set_interface_quirk(struct
+        * "Playback Design" products need a 50ms delay after setting the
+        * USB interface.
+        */
+-      if (le16_to_cpu(dev->descriptor.idVendor) == 0x23ba)
++      switch (le16_to_cpu(dev->descriptor.idVendor)) {
++      case 0x23ba: /* Playback Design */
++      case 0x0644: /* TEAC Corp. */
+               mdelay(50);
++              break;
++      }
+ }
+ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
+@@ -1218,6 +1222,14 @@ void snd_usb_ctl_msg_quirk(struct usb_de
+           (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
+               mdelay(20);
++      /*
++       * "TEAC Corp." products need a 20ms delay after each
++       * class compliant request
++       */
++      if ((le16_to_cpu(dev->descriptor.idVendor) == 0x0644) &&
++          (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
++              mdelay(20);
++
+       /* Marantz/Denon devices with USB DAC functionality need a delay
+        * after each class compliant request
+        */
diff --git a/queue-4.3/asoc-dpcm-fix-the-be-state-on-hw_free.patch b/queue-4.3/asoc-dpcm-fix-the-be-state-on-hw_free.patch
new file mode 100644 (file)
index 0000000..786920b
--- /dev/null
@@ -0,0 +1,39 @@
+From 5e82d2be6ee53275c72e964507518d7964c82753 Mon Sep 17 00:00:00 2001
+From: Vinod Koul <vinod.koul@intel.com>
+Date: Mon, 1 Feb 2016 22:26:40 +0530
+Subject: ASoC: dpcm: fix the BE state on hw_free
+
+From: Vinod Koul <vinod.koul@intel.com>
+
+commit 5e82d2be6ee53275c72e964507518d7964c82753 upstream.
+
+While performing hw_free, DPCM checks the BE state but leaves out
+the suspend state. The suspend state needs to be checked as well,
+as we might be suspended and then usermode closes rather than
+resuming the audio stream.
+
+This was found by a stress testing of system with playback in
+loop and killed after few seconds running in background and second
+script running suspend-resume test in loop
+
+Signed-off-by: Vinod Koul <vinod.koul@intel.com>
+Acked-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/soc/soc-pcm.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/sound/soc/soc-pcm.c
++++ b/sound/soc/soc-pcm.c
+@@ -1696,7 +1696,8 @@ int dpcm_be_dai_hw_free(struct snd_soc_p
+                   (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) &&
+                   (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
+                   (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED) &&
+-                  (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
++                  (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) &&
++                  (be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND))
+                       continue;
+               dev_dbg(be->dev, "ASoC: hw_free BE %s\n",
diff --git a/queue-4.3/asoc-rt5645-fix-the-shift-bit-of-in1-boost.patch b/queue-4.3/asoc-rt5645-fix-the-shift-bit-of-in1-boost.patch
new file mode 100644 (file)
index 0000000..aa09c85
--- /dev/null
@@ -0,0 +1,30 @@
+From b28785fa9cede0d4f47310ca0dd2a4e1d50478b5 Mon Sep 17 00:00:00 2001
+From: Bard Liao <bardliao@realtek.com>
+Date: Thu, 21 Jan 2016 13:13:40 +0800
+Subject: ASoC: rt5645: fix the shift bit of IN1 boost
+
+From: Bard Liao <bardliao@realtek.com>
+
+commit b28785fa9cede0d4f47310ca0dd2a4e1d50478b5 upstream.
+
+The shift bit of IN1 boost gain control is 12.
+
+Signed-off-by: Bard Liao <bardliao@realtek.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/soc/codecs/rt5645.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sound/soc/codecs/rt5645.c
++++ b/sound/soc/codecs/rt5645.c
+@@ -500,7 +500,7 @@ static const struct snd_kcontrol_new rt5
+       /* IN1/IN2 Control */
+       SOC_SINGLE_TLV("IN1 Boost", RT5645_IN1_CTRL1,
+-              RT5645_BST_SFT1, 8, 0, bst_tlv),
++              RT5645_BST_SFT1, 12, 0, bst_tlv),
+       SOC_SINGLE_TLV("IN2 Boost", RT5645_IN2_CTRL,
+               RT5645_BST_SFT2, 8, 0, bst_tlv),
diff --git a/queue-4.3/hrtimer-handle-remaining-time-proper-for-time_low_res.patch b/queue-4.3/hrtimer-handle-remaining-time-proper-for-time_low_res.patch
new file mode 100644 (file)
index 0000000..c7c25a8
--- /dev/null
@@ -0,0 +1,223 @@
+From 203cbf77de59fc8f13502dcfd11350c6d4a5c95f Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Jan 2016 16:54:46 +0000
+Subject: hrtimer: Handle remaining time proper for TIME_LOW_RES
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 203cbf77de59fc8f13502dcfd11350c6d4a5c95f upstream.
+
+If CONFIG_TIME_LOW_RES is enabled we add a jiffie to the relative timeout to
+prevent short sleeps, but we do not account for that in interfaces which
+retrieve the remaining time.
+
+Helge observed that timerfd can return a remaining time larger than the
+relative timeout. That's not expected and breaks userland test programs.
+
+Store the information that the timer was armed relative and provide functions
+to adjust the remaining time. To avoid bloating the hrtimer struct make state
+a u8, which as a bonus results in better code on x86 at least.
+
+Reported-and-tested-by: Helge Deller <deller@gmx.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: John Stultz <john.stultz@linaro.org>
+Cc: linux-m68k@lists.linux-m68k.org
+Cc: dhowells@redhat.com
+Link: http://lkml.kernel.org/r/20160114164159.273328486@linutronix.de
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/linux/hrtimer.h  |   34 ++++++++++++++++++++++++++---
+ kernel/time/hrtimer.c    |   55 +++++++++++++++++++++++++++++++----------------
+ kernel/time/timer_list.c |    2 -
+ 3 files changed, 69 insertions(+), 22 deletions(-)
+
+--- a/include/linux/hrtimer.h
++++ b/include/linux/hrtimer.h
+@@ -87,7 +87,8 @@ enum hrtimer_restart {
+  * @function: timer expiry callback function
+  * @base:     pointer to the timer base (per cpu and per clock)
+  * @state:    state information (See bit values above)
+- * @start_pid: timer statistics field to store the pid of the task which
++ * @is_rel:   Set if the timer was armed relative
++ * @start_pid:  timer statistics field to store the pid of the task which
+  *            started the timer
+  * @start_site:       timer statistics field to store the site where the timer
+  *            was started
+@@ -101,7 +102,8 @@ struct hrtimer {
+       ktime_t                         _softexpires;
+       enum hrtimer_restart            (*function)(struct hrtimer *);
+       struct hrtimer_clock_base       *base;
+-      unsigned long                   state;
++      u8                              state;
++      u8                              is_rel;
+ #ifdef CONFIG_TIMER_STATS
+       int                             start_pid;
+       void                            *start_site;
+@@ -321,6 +323,27 @@ static inline void clock_was_set_delayed
+ #endif
++static inline ktime_t
++__hrtimer_expires_remaining_adjusted(const struct hrtimer *timer, ktime_t now)
++{
++      ktime_t rem = ktime_sub(timer->node.expires, now);
++
++      /*
++       * Adjust relative timers for the extra we added in
++       * hrtimer_start_range_ns() to prevent short timeouts.
++       */
++      if (IS_ENABLED(CONFIG_TIME_LOW_RES) && timer->is_rel)
++              rem.tv64 -= hrtimer_resolution;
++      return rem;
++}
++
++static inline ktime_t
++hrtimer_expires_remaining_adjusted(const struct hrtimer *timer)
++{
++      return __hrtimer_expires_remaining_adjusted(timer,
++                                                  timer->base->get_time());
++}
++
+ extern void clock_was_set(void);
+ #ifdef CONFIG_TIMERFD
+ extern void timerfd_clock_was_set(void);
+@@ -390,7 +413,12 @@ static inline void hrtimer_restart(struc
+ }
+ /* Query timers: */
+-extern ktime_t hrtimer_get_remaining(const struct hrtimer *timer);
++extern ktime_t __hrtimer_get_remaining(const struct hrtimer *timer, bool adjust);
++
++static inline ktime_t hrtimer_get_remaining(const struct hrtimer *timer)
++{
++      return __hrtimer_get_remaining(timer, false);
++}
+ extern u64 hrtimer_get_next_event(void);
+--- a/kernel/time/hrtimer.c
++++ b/kernel/time/hrtimer.c
+@@ -897,10 +897,10 @@ static int enqueue_hrtimer(struct hrtime
+  */
+ static void __remove_hrtimer(struct hrtimer *timer,
+                            struct hrtimer_clock_base *base,
+-                           unsigned long newstate, int reprogram)
++                           u8 newstate, int reprogram)
+ {
+       struct hrtimer_cpu_base *cpu_base = base->cpu_base;
+-      unsigned int state = timer->state;
++      u8 state = timer->state;
+       timer->state = newstate;
+       if (!(state & HRTIMER_STATE_ENQUEUED))
+@@ -930,7 +930,7 @@ static inline int
+ remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base, bool restart)
+ {
+       if (hrtimer_is_queued(timer)) {
+-              unsigned long state = timer->state;
++              u8 state = timer->state;
+               int reprogram;
+               /*
+@@ -954,6 +954,22 @@ remove_hrtimer(struct hrtimer *timer, st
+       return 0;
+ }
++static inline ktime_t hrtimer_update_lowres(struct hrtimer *timer, ktime_t tim,
++                                          const enum hrtimer_mode mode)
++{
++#ifdef CONFIG_TIME_LOW_RES
++      /*
++       * CONFIG_TIME_LOW_RES indicates that the system has no way to return
++       * granular time values. For relative timers we add hrtimer_resolution
++       * (i.e. one jiffie) to prevent short timeouts.
++       */
++      timer->is_rel = mode & HRTIMER_MODE_REL;
++      if (timer->is_rel)
++              tim = ktime_add_safe(tim, ktime_set(0, hrtimer_resolution));
++#endif
++      return tim;
++}
++
+ /**
+  * hrtimer_start_range_ns - (re)start an hrtimer on the current CPU
+  * @timer:    the timer to be added
+@@ -974,19 +990,10 @@ void hrtimer_start_range_ns(struct hrtim
+       /* Remove an active timer from the queue: */
+       remove_hrtimer(timer, base, true);
+-      if (mode & HRTIMER_MODE_REL) {
++      if (mode & HRTIMER_MODE_REL)
+               tim = ktime_add_safe(tim, base->get_time());
+-              /*
+-               * CONFIG_TIME_LOW_RES is a temporary way for architectures
+-               * to signal that they simply return xtime in
+-               * do_gettimeoffset(). In this case we want to round up by
+-               * resolution when starting a relative timer, to avoid short
+-               * timeouts. This will go away with the GTOD framework.
+-               */
+-#ifdef CONFIG_TIME_LOW_RES
+-              tim = ktime_add_safe(tim, ktime_set(0, hrtimer_resolution));
+-#endif
+-      }
++
++      tim = hrtimer_update_lowres(timer, tim, mode);
+       hrtimer_set_expires_range_ns(timer, tim, delta_ns);
+@@ -1074,19 +1081,23 @@ EXPORT_SYMBOL_GPL(hrtimer_cancel);
+ /**
+  * hrtimer_get_remaining - get remaining time for the timer
+  * @timer:    the timer to read
++ * @adjust:   adjust relative timers when CONFIG_TIME_LOW_RES=y
+  */
+-ktime_t hrtimer_get_remaining(const struct hrtimer *timer)
++ktime_t __hrtimer_get_remaining(const struct hrtimer *timer, bool adjust)
+ {
+       unsigned long flags;
+       ktime_t rem;
+       lock_hrtimer_base(timer, &flags);
+-      rem = hrtimer_expires_remaining(timer);
++      if (IS_ENABLED(CONFIG_TIME_LOW_RES) && adjust)
++              rem = hrtimer_expires_remaining_adjusted(timer);
++      else
++              rem = hrtimer_expires_remaining(timer);
+       unlock_hrtimer_base(timer, &flags);
+       return rem;
+ }
+-EXPORT_SYMBOL_GPL(hrtimer_get_remaining);
++EXPORT_SYMBOL_GPL(__hrtimer_get_remaining);
+ #ifdef CONFIG_NO_HZ_COMMON
+ /**
+@@ -1220,6 +1231,14 @@ static void __run_hrtimer(struct hrtimer
+       fn = timer->function;
+       /*
++       * Clear the 'is relative' flag for the TIME_LOW_RES case. If the
++       * timer is restarted with a period then it becomes an absolute
++       * timer. If its not restarted it does not matter.
++       */
++      if (IS_ENABLED(CONFIG_TIME_LOW_RES))
++              timer->is_rel = false;
++
++      /*
+        * Because we run timers from hardirq context, there is no chance
+        * they get migrated to another cpu, therefore its safe to unlock
+        * the timer base.
+--- a/kernel/time/timer_list.c
++++ b/kernel/time/timer_list.c
+@@ -69,7 +69,7 @@ print_timer(struct seq_file *m, struct h
+       print_name_offset(m, taddr);
+       SEQ_printf(m, ", ");
+       print_name_offset(m, timer->function);
+-      SEQ_printf(m, ", S:%02lx", timer->state);
++      SEQ_printf(m, ", S:%02x", timer->state);
+ #ifdef CONFIG_TIMER_STATS
+       SEQ_printf(m, ", ");
+       print_name_offset(m, timer->start_site);
diff --git a/queue-4.3/n_tty-fix-poll-after-buffer-limited-eof-push-read.patch b/queue-4.3/n_tty-fix-poll-after-buffer-limited-eof-push-read.patch
new file mode 100644 (file)
index 0000000..6266575
--- /dev/null
@@ -0,0 +1,118 @@
+From ac8f3bf8832a405cc6e4dccb1d26d5cb2994d234 Mon Sep 17 00:00:00 2001
+From: Peter Hurley <peter@hurleysoftware.com>
+Date: Fri, 27 Nov 2015 13:59:20 -0500
+Subject: n_tty: Fix poll() after buffer-limited eof push read
+
+From: Peter Hurley <peter@hurleysoftware.com>
+
+commit ac8f3bf8832a405cc6e4dccb1d26d5cb2994d234 upstream.
+
+commit 40d5e0905a03 ("n_tty: Fix EOF push handling") fixed EOF push
+for reads. However, that approach still allows a condition mismatch
+between poll() and read(), where poll() returns POLLIN but read()
+blocks. This state can happen when a previous read() returned because
+the user buffer was full and the next character was an EOF not at the
+beginning of the line. While the next read() will properly identify
+the condition and advance the read buffer tail without improperly
+indicating an EOF file condition (ie., read() will not mistakenly
+return 0), poll() will mistakenly indicate POLLIN.
+
+Although a possible solution would be to peek at the input buffer
+in n_tty_poll(), the better solution in this patch is to eat the
+EOF during the previous read() (ie., fix the problem by eliminating
+the condition).
+
+The current canon line buffer copy limits the scan for next end-of-line
+to the smaller of either,
+   a. the remaining user buffer size
+   b. completed lines in the input buffer
+When the remaining user buffer size is exactly one less than the
+end-of-line marked by EOF push, the EOF is not scanned nor skipped
+but left for subsequent reads. In the example below, the scan
+index 'eol' has stopped at the EOF because it is past the scan
+limit of 5 (not because it has found the next set bit in read_flags)
+
+   user buffer [*nr = 5]    _ _ _ _ _
+
+   read_flags               0 0 0 0 0   1
+   input buffer             h e l l o [EOF]
+                            ^           ^
+                           /           /
+                         tail        eol
+
+   result: found = 0, tail += 5, *nr += 5
+
+Instead, allow the scan to peek ahead 1 byte (while still limiting the
+scan to completed lines in the input buffer). For the example above,
+
+   result: found = 1, tail += 6, *nr += 5
+
+Because the scan limit is now bumped +1 byte, when the scan is
+completed, the tail advance and the user buffer copy limit is
+re-clamped to *nr when EOF is _not_ found.
+
+Fixes: 40d5e0905a03 ("n_tty: Fix EOF push handling")
+Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/tty/n_tty.c |   22 +++++++++-------------
+ 1 file changed, 9 insertions(+), 13 deletions(-)
+
+--- a/drivers/tty/n_tty.c
++++ b/drivers/tty/n_tty.c
+@@ -2058,13 +2058,13 @@ static int canon_copy_from_read_buf(stru
+       size_t eol;
+       size_t tail;
+       int ret, found = 0;
+-      bool eof_push = 0;
+       /* N.B. avoid overrun if nr == 0 */
+-      n = min(*nr, smp_load_acquire(&ldata->canon_head) - ldata->read_tail);
+-      if (!n)
++      if (!*nr)
+               return 0;
++      n = min(*nr + 1, smp_load_acquire(&ldata->canon_head) - ldata->read_tail);
++
+       tail = ldata->read_tail & (N_TTY_BUF_SIZE - 1);
+       size = min_t(size_t, tail + n, N_TTY_BUF_SIZE);
+@@ -2085,12 +2085,11 @@ static int canon_copy_from_read_buf(stru
+       n = eol - tail;
+       if (n > N_TTY_BUF_SIZE)
+               n += N_TTY_BUF_SIZE;
+-      n += found;
+-      c = n;
++      c = n + found;
+-      if (found && !ldata->push && read_buf(ldata, eol) == __DISABLED_CHAR) {
+-              n--;
+-              eof_push = !n && ldata->read_tail != ldata->line_start;
++      if (!found || read_buf(ldata, eol) != __DISABLED_CHAR) {
++              c = min(*nr, c);
++              n = c;
+       }
+       n_tty_trace("%s: eol:%zu found:%d n:%zu c:%zu size:%zu more:%zu\n",
+@@ -2120,7 +2119,7 @@ static int canon_copy_from_read_buf(stru
+                       ldata->push = 0;
+               tty_audit_push(tty);
+       }
+-      return eof_push ? -EAGAIN : 0;
++      return 0;
+ }
+ extern ssize_t redirected_tty_write(struct file *, const char __user *,
+@@ -2299,10 +2298,7 @@ static ssize_t n_tty_read(struct tty_str
+               if (ldata->icanon && !L_EXTPROC(tty)) {
+                       retval = canon_copy_from_read_buf(tty, &b, &nr);
+-                      if (retval == -EAGAIN) {
+-                              retval = 0;
+-                              continue;
+-                      } else if (retval)
++                      if (retval)
+                               break;
+               } else {
+                       int uncopied;
diff --git a/queue-4.3/n_tty-fix-unsafe-reference-to-other-ldisc.patch b/queue-4.3/n_tty-fix-unsafe-reference-to-other-ldisc.patch
new file mode 100644 (file)
index 0000000..45facbf
--- /dev/null
@@ -0,0 +1,44 @@
+From 6d27a63caad3f13e96cf065d2d96828c2006be6b Mon Sep 17 00:00:00 2001
+From: Peter Hurley <peter@hurleysoftware.com>
+Date: Sun, 10 Jan 2016 22:40:56 -0800
+Subject: n_tty: Fix unsafe reference to "other" ldisc
+
+From: Peter Hurley <peter@hurleysoftware.com>
+
+commit 6d27a63caad3f13e96cf065d2d96828c2006be6b upstream.
+
+Although n_tty_check_unthrottle() has a valid ldisc reference (since
+the tty core gets the ldisc ref in tty_read() before calling the line
+discipline read() method), it does not have a valid ldisc reference to
+the "other" pty of a pty pair. Since getting an ldisc reference for
+tty->link essentially open-codes tty_wakeup(), just replace with the
+equivalent tty_wakeup().
+
+Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/tty/n_tty.c |    7 ++-----
+ 1 file changed, 2 insertions(+), 5 deletions(-)
+
+--- a/drivers/tty/n_tty.c
++++ b/drivers/tty/n_tty.c
+@@ -258,16 +258,13 @@ static void n_tty_check_throttle(struct
+ static void n_tty_check_unthrottle(struct tty_struct *tty)
+ {
+-      if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
+-          tty->link->ldisc->ops->write_wakeup == n_tty_write_wakeup) {
++      if (tty->driver->type == TTY_DRIVER_TYPE_PTY) {
+               if (chars_in_buffer(tty) > TTY_THRESHOLD_UNTHROTTLE)
+                       return;
+               if (!tty->count)
+                       return;
+               n_tty_kick_worker(tty);
+-              n_tty_write_wakeup(tty->link);
+-              if (waitqueue_active(&tty->link->write_wait))
+-                      wake_up_interruptible_poll(&tty->link->write_wait, POLLOUT);
++              tty_wakeup(tty->link);
+               return;
+       }
diff --git a/queue-4.3/revert-alsa-hda-fix-noise-on-gigabyte-z170x-mobo.patch b/queue-4.3/revert-alsa-hda-fix-noise-on-gigabyte-z170x-mobo.patch
new file mode 100644 (file)
index 0000000..b13059c
--- /dev/null
@@ -0,0 +1,70 @@
+From 6c361d10e0eb859233c71954abcd20d2d8700587 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Fri, 5 Feb 2016 20:12:24 +0100
+Subject: Revert "ALSA: hda - Fix noise on Gigabyte Z170X mobo"
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 6c361d10e0eb859233c71954abcd20d2d8700587 upstream.
+
+This reverts commit 0c25ad80408e95e0a4fbaf0056950206e95f726f.
+
+The original commit disabled the aamixer path due to the noise
+problem, but it turned out that some mobo with the same PCI SSID
+doesn't suffer from the issue, and the disabled function (analog
+loopback) is still demanded by users.
+
+Since the recent commit [e7fdd52779a6: ALSA: hda - Implement loopback
+control switch for Realtek and other codecs], we have the dynamic
+mixer switch to enable/disable the aamix path, and we don't have to
+disable the path statically any longer.  So, let's revert the
+disablement, so that only the user suffering from the noise problem
+can turn off the aamix on the fly.
+
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=108301
+Reported-by: <mutedbytes@gmail.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/pci/hda/patch_realtek.c |    8 --------
+ 1 file changed, 8 deletions(-)
+
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -1795,7 +1795,6 @@ enum {
+       ALC882_FIXUP_NO_PRIMARY_HP,
+       ALC887_FIXUP_ASUS_BASS,
+       ALC887_FIXUP_BASS_CHMAP,
+-      ALC882_FIXUP_DISABLE_AAMIX,
+ };
+ static void alc889_fixup_coef(struct hda_codec *codec,
+@@ -1957,8 +1956,6 @@ static void alc882_fixup_no_primary_hp(s
+ static void alc_fixup_bass_chmap(struct hda_codec *codec,
+                                const struct hda_fixup *fix, int action);
+-static void alc_fixup_disable_aamix(struct hda_codec *codec,
+-                                  const struct hda_fixup *fix, int action);
+ static const struct hda_fixup alc882_fixups[] = {
+       [ALC882_FIXUP_ABIT_AW9D_MAX] = {
+@@ -2196,10 +2193,6 @@ static const struct hda_fixup alc882_fix
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_bass_chmap,
+       },
+-      [ALC882_FIXUP_DISABLE_AAMIX] = {
+-              .type = HDA_FIXUP_FUNC,
+-              .v.func = alc_fixup_disable_aamix,
+-      },
+ };
+ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
+@@ -2267,7 +2260,6 @@ static const struct snd_pci_quirk alc882
+       SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
+       SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
+       SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
+-      SND_PCI_QUIRK(0x1458, 0xa182, "Gigabyte Z170X-UD3", ALC882_FIXUP_DISABLE_AAMIX),
+       SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
+       SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
+       SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
diff --git a/queue-4.3/saa7134-alsa-only-frees-registered-sound-cards.patch b/queue-4.3/saa7134-alsa-only-frees-registered-sound-cards.patch
new file mode 100644 (file)
index 0000000..0700c8f
--- /dev/null
@@ -0,0 +1,69 @@
+From ac75fe5d8fe4a0bf063be18fb29684405279e79e Mon Sep 17 00:00:00 2001
+From: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+Date: Thu, 4 Feb 2016 15:59:43 -0200
+Subject: [media] saa7134-alsa: Only frees registered sound cards
+
+From: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+
+commit ac75fe5d8fe4a0bf063be18fb29684405279e79e upstream.
+
+That prevents this bug:
+[ 2382.269496] BUG: unable to handle kernel NULL pointer dereference at 0000000000000540
+[ 2382.270013] IP: [<ffffffffa01fe616>] snd_card_free+0x36/0x70 [snd]
+[ 2382.270013] PGD 0
+[ 2382.270013] Oops: 0002 [#1] SMP
+[ 2382.270013] Modules linked in: saa7134_alsa(-) tda1004x saa7134_dvb videobuf2_dvb dvb_core tda827x tda8290 tuner saa7134 tveeprom videobuf2_dma_sg videobuf2_memops videobuf2_v4l2 videobuf2_core v4l2_common videodev media auth_rpcgss nfsv4 dns_resolver nfs lockd grace sunrpc tun bridge stp llc ebtables ip6table_filter ip6_tables nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack it87 hwmon_vid snd_hda_codec_idt snd_hda_codec_generic iTCO_wdt iTCO_vendor_support snd_hda_intel snd_hda_codec snd_hwdep snd_hda_core snd_seq pcspkr i2c_i801 snd_seq_device snd_pcm snd_timer lpc_ich snd mfd_core soundcore binfmt_misc i915 video i2c_algo_bit drm_kms_helper drm r8169 ata_generic serio_raw pata_acpi mii i2c_core [last unloaded: videobuf2_memops]
+[ 2382.270013] CPU: 0 PID: 4899 Comm: rmmod Not tainted 4.5.0-rc1+ #4
+[ 2382.270013] Hardware name: PCCHIPS P17G/P17G, BIOS 080012  05/14/2008
+[ 2382.270013] task: ffff880039c38000 ti: ffff88003c764000 task.ti: ffff88003c764000
+[ 2382.270013] RIP: 0010:[<ffffffffa01fe616>]  [<ffffffffa01fe616>] snd_card_free+0x36/0x70 [snd]
+[ 2382.270013] RSP: 0018:ffff88003c767ea0  EFLAGS: 00010286
+[ 2382.270013] RAX: ffff88003c767eb8 RBX: 0000000000000000 RCX: 0000000000006260
+[ 2382.270013] RDX: ffffffffa020a060 RSI: ffffffffa0206de1 RDI: ffff88003c767eb0
+[ 2382.270013] RBP: ffff88003c767ed8 R08: 0000000000019960 R09: ffffffff811a5412
+[ 2382.270013] R10: ffffea0000d7c200 R11: 0000000000000000 R12: ffff88003c767ea8
+[ 2382.270013] R13: 00007ffe760617f7 R14: 0000000000000000 R15: 0000557625d7f1e0
+[ 2382.270013] FS:  00007f80bb1c0700(0000) GS:ffff88003f400000(0000) knlGS:0000000000000000
+[ 2382.270013] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
+[ 2382.270013] CR2: 0000000000000540 CR3: 000000003c00f000 CR4: 00000000000006f0
+[ 2382.270013] Stack:
+[ 2382.270013]  000000003c767ed8 ffffffff00000000 ffff880000000000 ffff88003c767eb8
+[ 2382.270013]  ffff88003c767eb8 ffffffffa049a890 00007ffe76060060 ffff88003c767ef0
+[ 2382.270013]  ffffffffa049889d ffffffffa049a500 ffff88003c767f48 ffffffff8111079c
+[ 2382.270013] Call Trace:
+[ 2382.270013]  [<ffffffffa049889d>] saa7134_alsa_exit+0x1d/0x780 [saa7134_alsa]
+[ 2382.270013]  [<ffffffff8111079c>] SyS_delete_module+0x19c/0x1f0
+[ 2382.270013]  [<ffffffff8170fc2e>] entry_SYSCALL_64_fastpath+0x12/0x71
+[ 2382.270013] Code: 20 a0 48 c7 c6 e1 6d 20 a0 48 89 e5 41 54 53 4c 8d 65 d0 48 89 fb 48 83 ec 28 c7 45 d0 00 00 00 00 49 8d 7c 24 08 e8 7a 55 ed e0 <4c> 89 a3 40 05 00 00 48 89 df e8 eb fd ff ff 85 c0 75 1a 48 8d
+[ 2382.270013] RIP  [<ffffffffa01fe616>] snd_card_free+0x36/0x70 [snd]
+[ 2382.270013]  RSP <ffff88003c767ea0>
+[ 2382.270013] CR2: 0000000000000540
+
+Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/media/pci/saa7134/saa7134-alsa.c |    5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/media/pci/saa7134/saa7134-alsa.c
++++ b/drivers/media/pci/saa7134/saa7134-alsa.c
+@@ -1211,6 +1211,8 @@ static int alsa_device_init(struct saa71
+ static int alsa_device_exit(struct saa7134_dev *dev)
+ {
++      if (!snd_saa7134_cards[dev->nr])
++              return 1;
+       snd_card_free(snd_saa7134_cards[dev->nr]);
+       snd_saa7134_cards[dev->nr] = NULL;
+@@ -1260,7 +1262,8 @@ static void saa7134_alsa_exit(void)
+       int idx;
+       for (idx = 0; idx < SNDRV_CARDS; idx++) {
+-              snd_card_free(snd_saa7134_cards[idx]);
++              if (snd_saa7134_cards[idx])
++                      snd_card_free(snd_saa7134_cards[idx]);
+       }
+       saa7134_dmasound_init = NULL;
index 99fa0d31b20d7900768cc92dd959d89b2f16dfca..7f3611b28b5d83134ef6358bdc6699dd8b7fc196 100644 (file)
@@ -95,3 +95,51 @@ revert-ivtv-avoid-going-past-input-audio-array.patch
 mm-memcontrol-fix-possible-memcg-leak-due-to-interrupted-reclaim.patch
 md-raid10-fix-data-corruption-and-crash-during-resync.patch
 fix-sysvfs-symlinks.patch
+alsa-usb-audio-fix-teac-ud-501-ud-503-nt-503-usb-delay.patch
+alsa-usb-audio-add-quirk-for-microsoft-lifecam-hd-6000.patch
+alsa-usb-audio-fix-oppo-ha-1-vendor-id.patch
+alsa-usb-audio-add-native-dsd-support-for-ps-audio-nuwave-dac.patch
+alsa-usb-audio-avoid-freeing-umidi-object-twice.patch
+alsa-bebob-use-a-signed-return-type-for-get_formation_index.patch
+alsa-compress-disable-get_codec_caps-ioctl-for-some-architectures.patch
+alsa-dummy-disable-switching-timer-backend-via-sysfs.patch
+alsa-seq-fix-incorrect-sanity-check-at-snd_seq_oss_synth_cleanup.patch
+alsa-seq-degrade-the-error-message-for-too-many-opens.patch
+alsa-rawmidi-make-snd_rawmidi_transmit-race-free.patch
+alsa-rawmidi-remove-kernel-warning-for-null-user-space-buffer-check.patch
+alsa-rawmidi-fix-race-at-copying-updating-the-position.patch
+alsa-pcm-fix-potential-deadlock-in-oss-emulation.patch
+asoc-dpcm-fix-the-be-state-on-hw_free.patch
+alsa-seq-fix-yet-another-races-among-alsa-timer-accesses.patch
+alsa-seq-fix-race-at-closing-in-virmidi-driver.patch
+alsa-seq-fix-lockdep-warnings-due-to-double-mutex-locks.patch
+alsa-timer-fix-leftover-link-at-closing.patch
+alsa-timer-fix-link-corruption-due-to-double-start-or-stop.patch
+alsa-timer-fix-race-at-concurrent-reads.patch
+alsa-timer-fix-wrong-instance-passed-to-slave-callbacks.patch
+hrtimer-handle-remaining-time-proper-for-time_low_res.patch
+alsa-hda-add-fixup-for-mac-mini-7-1-model.patch
+alsa-hda-fix-static-checker-warning-in-patch_hdmi.c.patch
+revert-alsa-hda-fix-noise-on-gigabyte-z170x-mobo.patch
+alsa-hda-fix-speaker-output-from-vaio-aio-machines.patch
+alsa-hda-fix-bad-dereference-of-jack-object.patch
+alsa-dummy-implement-timer-backend-switching-more-safely.patch
+saa7134-alsa-only-frees-registered-sound-cards.patch
+asoc-rt5645-fix-the-shift-bit-of-in1-boost.patch
+usb-serial-visor-fix-crash-on-detecting-device-without-write_urbs.patch
+usb-visor-fix-null-deref-at-probe.patch
+usb-hub-do-not-clear-bos-field-during-reset-device.patch
+usb-serial-ftdi_sio-add-support-for-yaesu-scu-18-cable.patch
+usb-cp210x-add-id-for-iai-usb-to-rs485-adaptor.patch
+usb-serial-option-adding-support-for-telit-le922.patch
+usb-option-fix-cinterion-ahxx-enumeration.patch
+usb-cdc-acm-handle-unlinked-urb-in-acm-read-callback.patch
+usb-cdc-acm-send-zero-packet-for-intel-7260-modem.patch
+usb-phy-msm-fix-error-handling-in-probe.patch
+usb-xhci-handle-both-ssic-ports-in-pme-stuck-quirk.patch
+usb-xhci-apply-xhci_pme_stuck_quirk-to-intel-broxton-m-platforms.patch
+n_tty-fix-poll-after-buffer-limited-eof-push-read.patch
+n_tty-fix-unsafe-reference-to-other-ldisc.patch
+tty-fix-gpf-in-flush_to_ldisc.patch
+tty-retry-failed-reopen-if-tty-teardown-in-progress.patch
+tty-fix-unsafe-ldisc-reference-via-ioctl-tiocgetd.patch
diff --git a/queue-4.3/tty-fix-gpf-in-flush_to_ldisc.patch b/queue-4.3/tty-fix-gpf-in-flush_to_ldisc.patch
new file mode 100644 (file)
index 0000000..9d68ffb
--- /dev/null
@@ -0,0 +1,67 @@
+From 9ce119f318ba1a07c29149301f1544b6c4bea52a Mon Sep 17 00:00:00 2001
+From: Peter Hurley <peter@hurleysoftware.com>
+Date: Fri, 27 Nov 2015 14:25:08 -0500
+Subject: tty: Fix GPF in flush_to_ldisc()
+
+From: Peter Hurley <peter@hurleysoftware.com>
+
+commit 9ce119f318ba1a07c29149301f1544b6c4bea52a upstream.
+
+A line discipline which does not define a receive_buf() method can
+can cause a GPF if data is ever received [1]. Oddly, this was known
+to the author of n_tracesink in 2011, but never fixed.
+
+[1] GPF report
+    BUG: unable to handle kernel NULL pointer dereference at           (null)
+    IP: [<          (null)>]           (null)
+    PGD 3752d067 PUD 37a7b067 PMD 0
+    Oops: 0010 [#1] SMP KASAN
+    Modules linked in:
+    CPU: 2 PID: 148 Comm: kworker/u10:2 Not tainted 4.4.0-rc2+ #51
+    Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
+    Workqueue: events_unbound flush_to_ldisc
+    task: ffff88006da94440 ti: ffff88006db60000 task.ti: ffff88006db60000
+    RIP: 0010:[<0000000000000000>]  [<          (null)>]           (null)
+    RSP: 0018:ffff88006db67b50  EFLAGS: 00010246
+    RAX: 0000000000000102 RBX: ffff88003ab32f88 RCX: 0000000000000102
+    RDX: 0000000000000000 RSI: ffff88003ab330a6 RDI: ffff88003aabd388
+    RBP: ffff88006db67c48 R08: ffff88003ab32f9c R09: ffff88003ab31fb0
+    R10: ffff88003ab32fa8 R11: 0000000000000000 R12: dffffc0000000000
+    R13: ffff88006db67c20 R14: ffffffff863df820 R15: ffff88003ab31fb8
+    FS:  0000000000000000(0000) GS:ffff88006dc00000(0000) knlGS:0000000000000000
+    CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
+    CR2: 0000000000000000 CR3: 0000000037938000 CR4: 00000000000006e0
+    Stack:
+     ffffffff829f46f1 ffff88006da94bf8 ffff88006da94bf8 0000000000000000
+     ffff88003ab31fb0 ffff88003aabd438 ffff88003ab31ff8 ffff88006430fd90
+     ffff88003ab32f9c ffffed0007557a87 1ffff1000db6cf78 ffff88003ab32078
+    Call Trace:
+     [<ffffffff8127cf91>] process_one_work+0x8f1/0x17a0 kernel/workqueue.c:2030
+     [<ffffffff8127df14>] worker_thread+0xd4/0x1180 kernel/workqueue.c:2162
+     [<ffffffff8128faaf>] kthread+0x1cf/0x270 drivers/block/aoe/aoecmd.c:1302
+     [<ffffffff852a7c2f>] ret_from_fork+0x3f/0x70 arch/x86/entry/entry_64.S:468
+    Code:  Bad RIP value.
+    RIP  [<          (null)>]           (null)
+     RSP <ffff88006db67b50>
+    CR2: 0000000000000000
+    ---[ end trace a587f8947e54d6ea ]---
+
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/tty/tty_buffer.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/tty/tty_buffer.c
++++ b/drivers/tty/tty_buffer.c
+@@ -450,7 +450,7 @@ receive_buf(struct tty_struct *tty, stru
+               count = disc->ops->receive_buf2(tty, p, f, count);
+       else {
+               count = min_t(int, count, tty->receive_room);
+-              if (count)
++              if (count && disc->ops->receive_buf)
+                       disc->ops->receive_buf(tty, p, f, count);
+       }
+       return count;
diff --git a/queue-4.3/tty-fix-unsafe-ldisc-reference-via-ioctl-tiocgetd.patch b/queue-4.3/tty-fix-unsafe-ldisc-reference-via-ioctl-tiocgetd.patch
new file mode 100644 (file)
index 0000000..b2b4479
--- /dev/null
@@ -0,0 +1,68 @@
+From 5c17c861a357e9458001f021a7afa7aab9937439 Mon Sep 17 00:00:00 2001
+From: Peter Hurley <peter@hurleysoftware.com>
+Date: Sun, 10 Jan 2016 22:40:55 -0800
+Subject: tty: Fix unsafe ldisc reference via ioctl(TIOCGETD)
+
+From: Peter Hurley <peter@hurleysoftware.com>
+
+commit 5c17c861a357e9458001f021a7afa7aab9937439 upstream.
+
+ioctl(TIOCGETD) retrieves the line discipline id directly from the
+ldisc because the line discipline id (c_line) in termios is untrustworthy;
+userspace may have set termios via ioctl(TCSETS*) without actually
+changing the line discipline via ioctl(TIOCSETD).
+
+However, directly accessing the current ldisc via tty->ldisc is
+unsafe; the ldisc ptr dereferenced may be stale if the line discipline
+is changing via ioctl(TIOCSETD) or hangup.
+
+Wait for the line discipline reference (just like read() or write())
+to retrieve the "current" line discipline id.
+
+Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/tty/tty_io.c |   24 +++++++++++++++++++++++-
+ 1 file changed, 23 insertions(+), 1 deletion(-)
+
+--- a/drivers/tty/tty_io.c
++++ b/drivers/tty/tty_io.c
+@@ -2658,6 +2658,28 @@ static int tiocsetd(struct tty_struct *t
+ }
+ /**
++ *    tiocgetd        -       get line discipline
++ *    @tty: tty device
++ *    @p: pointer to user data
++ *
++ *    Retrieves the line discipline id directly from the ldisc.
++ *
++ *    Locking: waits for ldisc reference (in case the line discipline
++ *            is changing or the tty is being hungup)
++ */
++
++static int tiocgetd(struct tty_struct *tty, int __user *p)
++{
++      struct tty_ldisc *ld;
++      int ret;
++
++      ld = tty_ldisc_ref_wait(tty);
++      ret = put_user(ld->ops->num, p);
++      tty_ldisc_deref(ld);
++      return ret;
++}
++
++/**
+  *    send_break      -       performed time break
+  *    @tty: device to break on
+  *    @duration: timeout in mS
+@@ -2883,7 +2905,7 @@ long tty_ioctl(struct file *file, unsign
+       case TIOCGSID:
+               return tiocgsid(tty, real_tty, p);
+       case TIOCGETD:
+-              return put_user(tty->ldisc->ops->num, (int __user *)p);
++              return tiocgetd(tty, p);
+       case TIOCSETD:
+               return tiocsetd(tty, p);
+       case TIOCVHANGUP:
diff --git a/queue-4.3/tty-retry-failed-reopen-if-tty-teardown-in-progress.patch b/queue-4.3/tty-retry-failed-reopen-if-tty-teardown-in-progress.patch
new file mode 100644 (file)
index 0000000..a2be5ca
--- /dev/null
@@ -0,0 +1,58 @@
+From 7f22f6c935cda600660e623a411fe380015d28d9 Mon Sep 17 00:00:00 2001
+From: Peter Hurley <peter@hurleysoftware.com>
+Date: Sat, 9 Jan 2016 21:13:45 -0800
+Subject: tty: Retry failed reopen if tty teardown in-progress
+
+From: Peter Hurley <peter@hurleysoftware.com>
+
+commit 7f22f6c935cda600660e623a411fe380015d28d9 upstream.
+
+A small window exists where a tty reopen will observe the tty
+just prior to imminent teardown (tty->count == 0); in this case, open()
+returns EIO to userspace.
+
+Instead, retry the open after checking for signals and yielding;
+this interruptible retry loop allows teardown to commence and initialize
+a new tty on retry. Never retry the BSD master pty reopen; there is no
+guarantee the pty pair teardown is imminent since the slave file
+descriptors may remain open indefinitely.
+
+Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/tty/tty_io.c |   12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+--- a/drivers/tty/tty_io.c
++++ b/drivers/tty/tty_io.c
+@@ -1462,13 +1462,13 @@ static int tty_reopen(struct tty_struct
+ {
+       struct tty_driver *driver = tty->driver;
+-      if (!tty->count)
+-              return -EIO;
+-
+       if (driver->type == TTY_DRIVER_TYPE_PTY &&
+           driver->subtype == PTY_TYPE_MASTER)
+               return -EIO;
++      if (!tty->count)
++              return -EAGAIN;
++
+       if (test_bit(TTY_EXCLUSIVE, &tty->flags) && !capable(CAP_SYS_ADMIN))
+               return -EBUSY;
+@@ -2087,7 +2087,11 @@ retry_open:
+       if (IS_ERR(tty)) {
+               retval = PTR_ERR(tty);
+-              goto err_file;
++              if (retval != -EAGAIN || signal_pending(current))
++                      goto err_file;
++              tty_free_file(filp);
++              schedule();
++              goto retry_open;
+       }
+       tty_add_file(tty, filp);
diff --git a/queue-4.3/usb-cdc-acm-handle-unlinked-urb-in-acm-read-callback.patch b/queue-4.3/usb-cdc-acm-handle-unlinked-urb-in-acm-read-callback.patch
new file mode 100644 (file)
index 0000000..a636c07
--- /dev/null
@@ -0,0 +1,41 @@
+From 19454462acb1bdef80542061bdc9b410e4ed1ff6 Mon Sep 17 00:00:00 2001
+From: Lu Baolu <baolu.lu@linux.intel.com>
+Date: Wed, 30 Dec 2015 12:59:08 +0800
+Subject: usb: cdc-acm: handle unlinked urb in acm read callback
+
+From: Lu Baolu <baolu.lu@linux.intel.com>
+
+commit 19454462acb1bdef80542061bdc9b410e4ed1ff6 upstream.
+
+In current acm driver, the bulk-in callback function ignores the
+URBs unlinked in usb core.
+
+This causes unexpected data loss in some cases. For example,
+runtime suspend entry will unlinked all urbs and set urb->status
+to -ENOENT even those urbs might have data not processed yet.
+Hence, data loss occurs.
+
+This patch lets bulk-in callback function handle unlinked urbs
+to avoid data loss.
+
+Signed-off-by: Tang Jian Qiang <jianqiang.tang@intel.com>
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Acked-by: Oliver Neukum <oneukum@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/class/cdc-acm.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -428,7 +428,8 @@ static void acm_read_bulk_callback(struc
+               set_bit(rb->index, &acm->read_urbs_free);
+               dev_dbg(&acm->data->dev, "%s - non-zero urb status: %d\n",
+                                                       __func__, status);
+-              return;
++              if ((status != -ENOENT) || (urb->actual_length == 0))
++                      return;
+       }
+       usb_mark_last_busy(acm->dev);
diff --git a/queue-4.3/usb-cdc-acm-send-zero-packet-for-intel-7260-modem.patch b/queue-4.3/usb-cdc-acm-send-zero-packet-for-intel-7260-modem.patch
new file mode 100644 (file)
index 0000000..f5a1510
--- /dev/null
@@ -0,0 +1,52 @@
+From ffdb1e369a73b380fce95b05f8498d92c43842b4 Mon Sep 17 00:00:00 2001
+From: Lu Baolu <baolu.lu@linux.intel.com>
+Date: Wed, 6 Jan 2016 15:10:04 +0800
+Subject: usb: cdc-acm: send zero packet for intel 7260 modem
+
+From: Lu Baolu <baolu.lu@linux.intel.com>
+
+commit ffdb1e369a73b380fce95b05f8498d92c43842b4 upstream.
+
+For Intel 7260 modem, it is needed for host side to send zero
+packet if the BULK OUT size is equal to USB endpoint max packet
+length. Otherwise, modem side may still wait for more data and
+cannot give response to host side.
+
+Signed-off-by: Konrad Leszczynski <konrad.leszczynski@intel.com>
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/class/cdc-acm.c |    6 ++++++
+ drivers/usb/class/cdc-acm.h |    1 +
+ 2 files changed, 7 insertions(+)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -1405,6 +1405,8 @@ made_compressed_probe:
+                               usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
+                               NULL, acm->writesize, acm_write_bulk, snd);
+               snd->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
++              if (quirks & SEND_ZERO_PACKET)
++                      snd->urb->transfer_flags |= URB_ZERO_PACKET;
+               snd->instance = acm;
+       }
+@@ -1862,6 +1864,10 @@ static const struct usb_device_id acm_id
+       { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
+               USB_CDC_ACM_PROTO_AT_CDMA) },
++      { USB_DEVICE(0x1519, 0x0452), /* Intel 7260 modem */
++      .driver_info = SEND_ZERO_PACKET,
++      },
++
+       { }
+ };
+--- a/drivers/usb/class/cdc-acm.h
++++ b/drivers/usb/class/cdc-acm.h
+@@ -134,3 +134,4 @@ struct acm {
+ #define IGNORE_DEVICE                 BIT(5)
+ #define QUIRK_CONTROL_LINE_STATE      BIT(6)
+ #define CLEAR_HALT_CONDITIONS         BIT(7)
++#define SEND_ZERO_PACKET              BIT(8)
diff --git a/queue-4.3/usb-cp210x-add-id-for-iai-usb-to-rs485-adaptor.patch b/queue-4.3/usb-cp210x-add-id-for-iai-usb-to-rs485-adaptor.patch
new file mode 100644 (file)
index 0000000..57b264b
--- /dev/null
@@ -0,0 +1,30 @@
+From f487c54ddd544e1c9172cd510954f697b77b76e3 Mon Sep 17 00:00:00 2001
+From: Peter Dedecker <peter.dedecker@hotmail.com>
+Date: Fri, 8 Jan 2016 12:34:41 +0100
+Subject: USB: cp210x: add ID for IAI USB to RS485 adaptor
+
+From: Peter Dedecker <peter.dedecker@hotmail.com>
+
+commit f487c54ddd544e1c9172cd510954f697b77b76e3 upstream.
+
+Added the USB serial console device ID for IAI Corp. RCB-CV-USB
+USB to RS485 adaptor.
+
+Signed-off-by: Peter Dedecker <peter.dedecker@hotmail.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/cp210x.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/usb/serial/cp210x.c
++++ b/drivers/usb/serial/cp210x.c
+@@ -98,6 +98,7 @@ static const struct usb_device_id id_tab
+       { USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */
+       { USB_DEVICE(0x10C4, 0x81AD) }, /* INSYS USB Modem */
+       { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */
++      { USB_DEVICE(0x10C4, 0x81D7) }, /* IAI Corp. RCB-CV-USB USB to RS485 Adaptor */
+       { USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */
+       { USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */
+       { USB_DEVICE(0x10C4, 0x81E8) }, /* Zephyr Bioharness */
diff --git a/queue-4.3/usb-hub-do-not-clear-bos-field-during-reset-device.patch b/queue-4.3/usb-hub-do-not-clear-bos-field-during-reset-device.patch
new file mode 100644 (file)
index 0000000..cc99906
--- /dev/null
@@ -0,0 +1,61 @@
+From d8f00cd685f5c8e0def8593e520a7fef12c22407 Mon Sep 17 00:00:00 2001
+From: "Du, Changbin" <changbin.du@intel.com>
+Date: Mon, 18 Jan 2016 21:02:42 +0800
+Subject: usb: hub: do not clear BOS field during reset device
+
+From: Du, Changbin <changbin.du@intel.com>
+
+commit d8f00cd685f5c8e0def8593e520a7fef12c22407 upstream.
+
+In function usb_reset_and_verify_device, the old BOS descriptor may
+still be used before allocating a new one. (usb_unlocked_disable_lpm
+function uses it under the situation that it fails to disable lpm.)
+So we cannot set the udev->bos to NULL before that, just keep what it
+was. It will be overwrite when allocating a new one.
+
+Crash log:
+BUG: unable to handle kernel NULL pointer dereference at
+0000000000000010
+IP: [<ffffffff8171f98d>] usb_enable_link_state+0x2d/0x2f0
+Call Trace:
+[<ffffffff8171ed5b>] ? usb_set_lpm_timeout+0x12b/0x140
+[<ffffffff8171fcd1>] usb_enable_lpm+0x81/0xa0
+[<ffffffff8171fdd8>] usb_disable_lpm+0xa8/0xc0
+[<ffffffff8171fe1c>] usb_unlocked_disable_lpm+0x2c/0x50
+[<ffffffff81723933>] usb_reset_and_verify_device+0xc3/0x710
+[<ffffffff8172c4ed>] ? usb_sg_wait+0x13d/0x190
+[<ffffffff81724743>] usb_reset_device+0x133/0x280
+[<ffffffff8179ccd1>] usb_stor_port_reset+0x61/0x70
+[<ffffffff8179cd68>] usb_stor_invoke_transport+0x88/0x520
+
+Signed-off-by: Du, Changbin <changbin.du@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/core/hub.c |    8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -5377,7 +5377,6 @@ static int usb_reset_and_verify_device(s
+       }
+       bos = udev->bos;
+-      udev->bos = NULL;
+       for (i = 0; i < SET_CONFIG_TRIES; ++i) {
+@@ -5470,8 +5469,11 @@ done:
+       usb_set_usb2_hardware_lpm(udev, 1);
+       usb_unlocked_enable_lpm(udev);
+       usb_enable_ltm(udev);
+-      usb_release_bos_descriptor(udev);
+-      udev->bos = bos;
++      /* release the new BOS descriptor allocated  by hub_port_init() */
++      if (udev->bos != bos) {
++              usb_release_bos_descriptor(udev);
++              udev->bos = bos;
++      }
+       return 0;
+ re_enumerate:
diff --git a/queue-4.3/usb-option-fix-cinterion-ahxx-enumeration.patch b/queue-4.3/usb-option-fix-cinterion-ahxx-enumeration.patch
new file mode 100644 (file)
index 0000000..78e40f0
--- /dev/null
@@ -0,0 +1,48 @@
+From 4152b387da81617c80cb2946b2d56e3958906b3e Mon Sep 17 00:00:00 2001
+From: John Ernberg <john.ernberg@actia.se>
+Date: Mon, 25 Jan 2016 12:27:17 +0000
+Subject: USB: option: fix Cinterion AHxx enumeration
+
+From: John Ernberg <john.ernberg@actia.se>
+
+commit 4152b387da81617c80cb2946b2d56e3958906b3e upstream.
+
+In certain kernel configurations where the cdc_ether and option drivers
+are compiled as modules there can occur a race condition in enumeration.
+This causes the option driver to enumerate the ethernet(wwan) interface
+as usb-serial interfaces.
+
+usb-devices output for the modem:
+T:  Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  5 Spd=480 MxCh= 0
+D:  Ver= 2.00 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs=  1
+P:  Vendor=1e2d ProdID=0055 Rev=00.00
+S:  Manufacturer=Cinterion
+S:  Product=AHx
+C:  #Ifs= 6 Cfg#= 1 Atr=e0 MxPwr=10mA
+I:  If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option
+I:  If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option
+I:  If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option
+I:  If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=option
+I:  If#= 4 Alt= 0 #EPs= 1 Cls=02(commc) Sub=06 Prot=00 Driver=cdc_ether
+I:  If#= 5 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=cdc_ether
+
+Signed-off-by: John Ernberg <john.ernberg@actia.se>
+Fixes: 1941138e1c02 ("USB: added support for Cinterion's products...")
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/option.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -1707,7 +1707,7 @@ static const struct usb_device_id option
+       { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) },
+       { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8),
+               .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+-      { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX) },
++      { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX, 0xff) },
+       { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PLXX),
+               .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+       { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) }, 
diff --git a/queue-4.3/usb-phy-msm-fix-error-handling-in-probe.patch b/queue-4.3/usb-phy-msm-fix-error-handling-in-probe.patch
new file mode 100644 (file)
index 0000000..2dc2fa3
--- /dev/null
@@ -0,0 +1,149 @@
+From a38a08dfaaab978dced63aa9cad45f0f62e23a66 Mon Sep 17 00:00:00 2001
+From: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Date: Wed, 13 Jan 2016 09:13:10 +0000
+Subject: usb: phy: msm: fix error handling in probe.
+
+From: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+commit a38a08dfaaab978dced63aa9cad45f0f62e23a66 upstream.
+
+This driver registers for extcon events as part of its probe, but
+never unregisters them in case of error in the probe path.
+
+There were multiple issues noticed due to this missing error handling.
+One of them is random crashes if the regulators are not ready yet by the
+time probe is invoked.
+
+Ivan's previous attempt [1] to fix this issue, did not really address
+all the failure cases like regualtor/get_irq failures.
+
+[1] https://lkml.org/lkml/2015/9/7/62
+
+Without this patch the kernel would carsh with log:
+...
+Unable to handle kernel paging request at virtual address 17d78410
+pgd = ffffffc001a5c000
+[17d78410] *pgd=00000000b6806003, *pud=00000000b6806003, *pmd=0000000000000000
+Internal error: Oops: 96000005 [#1] PREEMPT SMP
+Modules linked in:
+CPU: 0 PID: 6 Comm: kworker/u8:0 Not tainted 4.4.0+ #48
+Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT)
+Workqueue: deferwq deferred_probe_work_func
+task: ffffffc03686e900 ti: ffffffc0368b0000 task.ti: ffffffc0368b0000
+PC is at raw_notifier_chain_register+0x1c/0x44
+LR is at extcon_register_notifier+0x88/0xc8
+pc : [<ffffffc0000da43c>] lr : [<ffffffc000606298>] pstate: 80000085
+sp : ffffffc0368b3a70
+x29: ffffffc0368b3a70 x28: ffffffc03680c310
+x27: ffffffc035518000 x26: ffffffc035518000
+x25: ffffffc03bfa20e0 x24: ffffffc035580a18
+x23: 0000000000000000 x22: ffffffc035518458
+x21: ffffffc0355e9a60 x20: ffffffc035518000
+x19: 0000000000000000 x18: 0000000000000028
+x17: 0000000000000003 x16: ffffffc0018153c8
+x15: 0000000000000001 x14: ffffffc03686f0f8
+x13: ffffffc03686f0f8 x12: 0000000000000003
+x11: 0000000000000001 x10: 0000000000000001
+x9 : ffffffc03686f0f8 x8 : 0000e3872014c1a1
+x7 : 0000000000000028 x6 : 0000000000000000
+x5 : 0000000000000001 x4 : 0000000000000000
+x3 : 00000000354fb170 x2 : 0000000017d78400
+x1 : ffffffc0355e9a60 x0 : ffffffc0354fb268
+
+Fixes:         591fc116f330 ("usb: phy: msm: Use extcon framework for VBUS and ID detection")
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Signed-off-by: Felipe Balbi <balbi@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/phy/phy-msm-usb.c |   37 ++++++++++++++++++++++++-------------
+ 1 file changed, 24 insertions(+), 13 deletions(-)
+
+--- a/drivers/usb/phy/phy-msm-usb.c
++++ b/drivers/usb/phy/phy-msm-usb.c
+@@ -1599,6 +1599,8 @@ static int msm_otg_read_dt(struct platfo
+                                               &motg->id.nb);
+               if (ret < 0) {
+                       dev_err(&pdev->dev, "register ID notifier failed\n");
++                      extcon_unregister_notifier(motg->vbus.extcon,
++                                                 EXTCON_USB, &motg->vbus.nb);
+                       return ret;
+               }
+@@ -1660,15 +1662,6 @@ static int msm_otg_probe(struct platform
+       if (!motg)
+               return -ENOMEM;
+-      pdata = dev_get_platdata(&pdev->dev);
+-      if (!pdata) {
+-              if (!np)
+-                      return -ENXIO;
+-              ret = msm_otg_read_dt(pdev, motg);
+-              if (ret)
+-                      return ret;
+-      }
+-
+       motg->phy.otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg),
+                                    GFP_KERNEL);
+       if (!motg->phy.otg)
+@@ -1710,6 +1703,15 @@ static int msm_otg_probe(struct platform
+       if (!motg->regs)
+               return -ENOMEM;
++      pdata = dev_get_platdata(&pdev->dev);
++      if (!pdata) {
++              if (!np)
++                      return -ENXIO;
++              ret = msm_otg_read_dt(pdev, motg);
++              if (ret)
++                      return ret;
++      }
++
+       /*
+        * NOTE: The PHYs can be multiplexed between the chipidea controller
+        * and the dwc3 controller, using a single bit. It is important that
+@@ -1717,8 +1719,10 @@ static int msm_otg_probe(struct platform
+        */
+       if (motg->phy_number) {
+               phy_select = devm_ioremap_nocache(&pdev->dev, USB2_PHY_SEL, 4);
+-              if (!phy_select)
+-                      return -ENOMEM;
++              if (!phy_select) {
++                      ret = -ENOMEM;
++                      goto unregister_extcon;
++              }
+               /* Enable second PHY with the OTG port */
+               writel(0x1, phy_select);
+       }
+@@ -1728,7 +1732,8 @@ static int msm_otg_probe(struct platform
+       motg->irq = platform_get_irq(pdev, 0);
+       if (motg->irq < 0) {
+               dev_err(&pdev->dev, "platform_get_irq failed\n");
+-              return motg->irq;
++              ret = motg->irq;
++              goto unregister_extcon;
+       }
+       regs[0].supply = "vddcx";
+@@ -1737,7 +1742,7 @@ static int msm_otg_probe(struct platform
+       ret = devm_regulator_bulk_get(motg->phy.dev, ARRAY_SIZE(regs), regs);
+       if (ret)
+-              return ret;
++              goto unregister_extcon;
+       motg->vddcx = regs[0].consumer;
+       motg->v3p3  = regs[1].consumer;
+@@ -1834,6 +1839,12 @@ disable_clks:
+       clk_disable_unprepare(motg->clk);
+       if (!IS_ERR(motg->core_clk))
+               clk_disable_unprepare(motg->core_clk);
++unregister_extcon:
++      extcon_unregister_notifier(motg->id.extcon,
++                                 EXTCON_USB_HOST, &motg->id.nb);
++      extcon_unregister_notifier(motg->vbus.extcon,
++                                 EXTCON_USB, &motg->vbus.nb);
++
+       return ret;
+ }
diff --git a/queue-4.3/usb-serial-ftdi_sio-add-support-for-yaesu-scu-18-cable.patch b/queue-4.3/usb-serial-ftdi_sio-add-support-for-yaesu-scu-18-cable.patch
new file mode 100644 (file)
index 0000000..98fdd94
--- /dev/null
@@ -0,0 +1,43 @@
+From e03cdf22a2727c60307be6a729233edab3bfda9c Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Tue, 19 Jan 2016 23:43:13 -0800
+Subject: USB: serial: ftdi_sio: add support for Yaesu SCU-18 cable
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+commit e03cdf22a2727c60307be6a729233edab3bfda9c upstream.
+
+Harald Linden reports that the ftdi_sio driver works properly for the
+Yaesu SCU-18 cable if the device ids are added to the driver.  So let's
+add them.
+
+Reported-by: Harald Linden <harald.linden@7183.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/ftdi_sio.c     |    1 +
+ drivers/usb/serial/ftdi_sio_ids.h |    1 +
+ 2 files changed, 2 insertions(+)
+
+--- a/drivers/usb/serial/ftdi_sio.c
++++ b/drivers/usb/serial/ftdi_sio.c
+@@ -824,6 +824,7 @@ static const struct usb_device_id id_tab
+       { USB_DEVICE(FTDI_VID, FTDI_TURTELIZER_PID),
+               .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+       { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) },
++      { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_SCU18) },
+       { USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) },
+       /* Papouch devices based on FTDI chip */
+--- a/drivers/usb/serial/ftdi_sio_ids.h
++++ b/drivers/usb/serial/ftdi_sio_ids.h
+@@ -615,6 +615,7 @@
+  */
+ #define RATOC_VENDOR_ID               0x0584
+ #define RATOC_PRODUCT_ID_USB60F       0xb020
++#define RATOC_PRODUCT_ID_SCU18        0xb03a
+ /*
+  * Infineon Technologies
diff --git a/queue-4.3/usb-serial-option-adding-support-for-telit-le922.patch b/queue-4.3/usb-serial-option-adding-support-for-telit-le922.patch
new file mode 100644 (file)
index 0000000..835a32e
--- /dev/null
@@ -0,0 +1,58 @@
+From ff4e2494dc17b173468e1713fdf6237fd8578bc7 Mon Sep 17 00:00:00 2001
+From: Daniele Palmas <dnlplm@gmail.com>
+Date: Tue, 12 Jan 2016 17:22:06 +0100
+Subject: USB: serial: option: Adding support for Telit LE922
+
+From: Daniele Palmas <dnlplm@gmail.com>
+
+commit ff4e2494dc17b173468e1713fdf6237fd8578bc7 upstream.
+
+This patch adds support for two PIDs of LE922.
+
+Signed-off-by: Daniele Palmas <dnlplm@gmail.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/option.c |   16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -271,6 +271,8 @@ static void option_instat_callback(struc
+ #define TELIT_PRODUCT_CC864_SINGLE            0x1006
+ #define TELIT_PRODUCT_DE910_DUAL              0x1010
+ #define TELIT_PRODUCT_UE910_V2                        0x1012
++#define TELIT_PRODUCT_LE922_USBCFG0           0x1042
++#define TELIT_PRODUCT_LE922_USBCFG3           0x1043
+ #define TELIT_PRODUCT_LE920                   0x1200
+ #define TELIT_PRODUCT_LE910                   0x1201
+@@ -623,6 +625,16 @@ static const struct option_blacklist_inf
+       .reserved = BIT(8) | BIT(10) | BIT(11),
+ };
++static const struct option_blacklist_info telit_le922_blacklist_usbcfg0 = {
++      .sendsetup = BIT(2),
++      .reserved = BIT(0) | BIT(1) | BIT(3),
++};
++
++static const struct option_blacklist_info telit_le922_blacklist_usbcfg3 = {
++      .sendsetup = BIT(0),
++      .reserved = BIT(1) | BIT(2) | BIT(3),
++};
++
+ static const struct usb_device_id option_ids[] = {
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
+@@ -1172,6 +1184,10 @@ static const struct usb_device_id option
+       { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) },
+       { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) },
+       { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UE910_V2) },
++      { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG0),
++              .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 },
++      { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG3),
++              .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 },
+       { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910),
+               .driver_info = (kernel_ulong_t)&telit_le910_blacklist },
+       { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920),
diff --git a/queue-4.3/usb-serial-visor-fix-crash-on-detecting-device-without-write_urbs.patch b/queue-4.3/usb-serial-visor-fix-crash-on-detecting-device-without-write_urbs.patch
new file mode 100644 (file)
index 0000000..b94579f
--- /dev/null
@@ -0,0 +1,38 @@
+From cb3232138e37129e88240a98a1d2aba2187ff57c Mon Sep 17 00:00:00 2001
+From: Vladis Dronov <vdronov@redhat.com>
+Date: Tue, 12 Jan 2016 15:10:50 +0100
+Subject: USB: serial: visor: fix crash on detecting device without write_urbs
+
+From: Vladis Dronov <vdronov@redhat.com>
+
+commit cb3232138e37129e88240a98a1d2aba2187ff57c upstream.
+
+The visor driver crashes in clie_5_attach() when a specially crafted USB
+device without bulk-out endpoint is detected. This fix adds a check that
+the device has proper configuration expected by the driver.
+
+Reported-by: Ralf Spenneberg <ralf@spenneberg.net>
+Signed-off-by: Vladis Dronov <vdronov@redhat.com>
+Fixes: cfb8da8f69b8 ("USB: visor: fix initialisation of UX50/TH55 devices")
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/visor.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/serial/visor.c
++++ b/drivers/usb/serial/visor.c
+@@ -597,8 +597,10 @@ static int clie_5_attach(struct usb_seri
+        */
+       /* some sanity check */
+-      if (serial->num_ports < 2)
+-              return -1;
++      if (serial->num_bulk_out < 2) {
++              dev_err(&serial->interface->dev, "missing bulk out endpoints\n");
++              return -ENODEV;
++      }
+       /* port 0 now uses the modified endpoint Address */
+       port = serial->port[0];
diff --git a/queue-4.3/usb-visor-fix-null-deref-at-probe.patch b/queue-4.3/usb-visor-fix-null-deref-at-probe.patch
new file mode 100644 (file)
index 0000000..809ed72
--- /dev/null
@@ -0,0 +1,38 @@
+From cac9b50b0d75a1d50d6c056ff65c005f3224c8e0 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Tue, 12 Jan 2016 12:05:20 +0100
+Subject: USB: visor: fix null-deref at probe
+
+From: Johan Hovold <johan@kernel.org>
+
+commit cac9b50b0d75a1d50d6c056ff65c005f3224c8e0 upstream.
+
+Fix null-pointer dereference at probe should a (malicious) Treo device
+lack the expected endpoints.
+
+Specifically, the Treo port-setup hack was dereferencing the bulk-in and
+interrupt-in urbs without first making sure they had been allocated by
+core.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/visor.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/usb/serial/visor.c
++++ b/drivers/usb/serial/visor.c
+@@ -544,6 +544,11 @@ static int treo_attach(struct usb_serial
+               (serial->num_interrupt_in == 0))
+               return 0;
++      if (serial->num_bulk_in < 2 || serial->num_interrupt_in < 2) {
++              dev_err(&serial->interface->dev, "missing endpoints\n");
++              return -ENODEV;
++      }
++
+       /*
+       * It appears that Treos and Kyoceras want to use the
+       * 1st bulk in endpoint to communicate with the 2nd bulk out endpoint,
diff --git a/queue-4.3/usb-xhci-apply-xhci_pme_stuck_quirk-to-intel-broxton-m-platforms.patch b/queue-4.3/usb-xhci-apply-xhci_pme_stuck_quirk-to-intel-broxton-m-platforms.patch
new file mode 100644 (file)
index 0000000..90be611
--- /dev/null
@@ -0,0 +1,39 @@
+From ccc04afb72cddbdf7c0e1c17e92886405a71b754 Mon Sep 17 00:00:00 2001
+From: Lu Baolu <baolu.lu@linux.intel.com>
+Date: Tue, 26 Jan 2016 17:50:08 +0200
+Subject: usb: xhci: apply XHCI_PME_STUCK_QUIRK to Intel Broxton-M platforms
+
+From: Lu Baolu <baolu.lu@linux.intel.com>
+
+commit ccc04afb72cddbdf7c0e1c17e92886405a71b754 upstream.
+
+Intel Broxton M was verifed to require XHCI_PME_STUCK_QUIRK quirk as well.
+
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci-pci.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -47,6 +47,7 @@
+ #define PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI           0x22b5
+ #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI               0xa12f
+ #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI      0x9d2f
++#define PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI            0x0aa8
+ static const char hcd_name[] = "xhci_hcd";
+@@ -154,7 +155,8 @@ static void xhci_pci_quirks(struct devic
+       if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
+               (pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI ||
+                pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI ||
+-               pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI)) {
++               pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI ||
++               pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI)) {
+               xhci->quirks |= XHCI_PME_STUCK_QUIRK;
+       }
+       if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
diff --git a/queue-4.3/usb-xhci-handle-both-ssic-ports-in-pme-stuck-quirk.patch b/queue-4.3/usb-xhci-handle-both-ssic-ports-in-pme-stuck-quirk.patch
new file mode 100644 (file)
index 0000000..3bc2525
--- /dev/null
@@ -0,0 +1,92 @@
+From fa89537783cb442263fa5a14df6c7693eaf32f11 Mon Sep 17 00:00:00 2001
+From: Lu Baolu <baolu.lu@linux.intel.com>
+Date: Tue, 26 Jan 2016 17:50:05 +0200
+Subject: usb: xhci: handle both SSIC ports in PME stuck quirk
+
+From: Lu Baolu <baolu.lu@linux.intel.com>
+
+commit fa89537783cb442263fa5a14df6c7693eaf32f11 upstream.
+
+Commit abce329c27b3 ("xhci: Workaround to get D3 working in Intel xHCI")
+adds a workaround for a limitation of PME storm caused by SSIC port in
+some Intel SoCs. This commit only handled one SSIC port, while there
+are actually two SSIC ports in the chips. This patch handles both SSIC
+ports. Without this fix, users still see PME storm.
+
+Signed-off-by: Zhuang Jin Can <jin.can.zhuang@intel.com>
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci-pci.c |   48 ++++++++++++++++++++++++++------------------
+ 1 file changed, 29 insertions(+), 19 deletions(-)
+
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -28,7 +28,9 @@
+ #include "xhci.h"
+ #include "xhci-trace.h"
+-#define PORT2_SSIC_CONFIG_REG2        0x883c
++#define SSIC_PORT_NUM         2
++#define SSIC_PORT_CFG2                0x880c
++#define SSIC_PORT_CFG2_OFFSET 0x30
+ #define PROG_DONE             (1 << 30)
+ #define SSIC_PORT_UNUSED      (1 << 31)
+@@ -316,28 +318,36 @@ static void xhci_pme_quirk(struct usb_hc
+       struct pci_dev          *pdev = to_pci_dev(hcd->self.controller);
+       u32 val;
+       void __iomem *reg;
++      int i;
+       if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
+                pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) {
+-              reg = (void __iomem *) xhci->cap_regs + PORT2_SSIC_CONFIG_REG2;
+-
+-              /* Notify SSIC that SSIC profile programming is not done */
+-              val = readl(reg) & ~PROG_DONE;
+-              writel(val, reg);
+-
+-              /* Mark SSIC port as unused(suspend) or used(resume) */
+-              val = readl(reg);
+-              if (suspend)
+-                      val |= SSIC_PORT_UNUSED;
+-              else
+-                      val &= ~SSIC_PORT_UNUSED;
+-              writel(val, reg);
+-
+-              /* Notify SSIC that SSIC profile programming is done */
+-              val = readl(reg) | PROG_DONE;
+-              writel(val, reg);
+-              readl(reg);
++              for (i = 0; i < SSIC_PORT_NUM; i++) {
++                      reg = (void __iomem *) xhci->cap_regs +
++                                      SSIC_PORT_CFG2 +
++                                      i * SSIC_PORT_CFG2_OFFSET;
++
++                      /*
++                       * Notify SSIC that SSIC profile programming
++                       * is not done.
++                       */
++                      val = readl(reg) & ~PROG_DONE;
++                      writel(val, reg);
++
++                      /* Mark SSIC port as unused(suspend) or used(resume) */
++                      val = readl(reg);
++                      if (suspend)
++                              val |= SSIC_PORT_UNUSED;
++                      else
++                              val &= ~SSIC_PORT_UNUSED;
++                      writel(val, reg);
++
++                      /* Notify SSIC that SSIC profile programming is done */
++                      val = readl(reg) | PROG_DONE;
++                      writel(val, reg);
++                      readl(reg);
++              }
+       }
+       reg = (void __iomem *) xhci->cap_regs + 0x80a4;