]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 11 Jan 2018 07:18:22 +0000 (08:18 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 11 Jan 2018 07:18:22 +0000 (08:18 +0100)
added patches:
alsa-aloop-fix-inconsistent-format-due-to-incomplete-rule.patch
alsa-aloop-fix-racy-hw-constraints-adjustment.patch
alsa-aloop-release-cable-upon-open-error-path.patch
alsa-pcm-abort-properly-at-pending-signal-in-oss-read-write-loops.patch
alsa-pcm-add-missing-error-checks-in-oss-emulation-plugin-builder.patch
alsa-pcm-allow-aborting-mutex-lock-at-oss-read-write-loops.patch
alsa-pcm-remove-incorrect-snd_bug_on-usages.patch
nvmem-add-i.mx7-support-to-snvs-lpgpr.patch

queue-4.4/alsa-aloop-fix-inconsistent-format-due-to-incomplete-rule.patch [new file with mode: 0644]
queue-4.4/alsa-aloop-fix-racy-hw-constraints-adjustment.patch [new file with mode: 0644]
queue-4.4/alsa-aloop-release-cable-upon-open-error-path.patch [new file with mode: 0644]
queue-4.4/alsa-pcm-abort-properly-at-pending-signal-in-oss-read-write-loops.patch [new file with mode: 0644]
queue-4.4/alsa-pcm-add-missing-error-checks-in-oss-emulation-plugin-builder.patch [new file with mode: 0644]
queue-4.4/alsa-pcm-allow-aborting-mutex-lock-at-oss-read-write-loops.patch [new file with mode: 0644]
queue-4.4/alsa-pcm-remove-incorrect-snd_bug_on-usages.patch [new file with mode: 0644]
queue-4.4/nvmem-add-i.mx7-support-to-snvs-lpgpr.patch [new file with mode: 0644]
queue-4.4/series

diff --git a/queue-4.4/alsa-aloop-fix-inconsistent-format-due-to-incomplete-rule.patch b/queue-4.4/alsa-aloop-fix-inconsistent-format-due-to-incomplete-rule.patch
new file mode 100644 (file)
index 0000000..55f1115
--- /dev/null
@@ -0,0 +1,65 @@
+From b088b53e20c7d09b5ab84c5688e609f478e5c417 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Fri, 5 Jan 2018 16:15:33 +0100
+Subject: ALSA: aloop: Fix inconsistent format due to incomplete rule
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit b088b53e20c7d09b5ab84c5688e609f478e5c417 upstream.
+
+The extra hw constraint rule for the formats the aloop driver
+introduced has a slight flaw, where it doesn't return a positive value
+when the mask got changed.  It came from the fact that it's basically
+a copy&paste from snd_hw_constraint_mask64().  The original code is
+supposed to be a single-shot and it modifies the mask bits only once
+and never after, while what we need for aloop is the dynamic hw rule
+that limits the mask bits.
+
+This difference results in the inconsistent state, as the hw_refine
+doesn't apply the dependencies fully.  The worse and surprisingly
+result is that it causes a crash in OSS emulation when multiple
+full-duplex reads/writes are performed concurrently (I leave why it
+triggers Oops to readers as a homework).
+
+For fixing this, replace a few open-codes with the standard
+snd_mask_*() macros.
+
+Reported-by: syzbot+3902b5220e8ca27889ca@syzkaller.appspotmail.com
+Fixes: b1c73fc8e697 ("ALSA: snd-aloop: Fix hw_params restrictions and checking")
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/drivers/aloop.c |   13 ++++++-------
+ 1 file changed, 6 insertions(+), 7 deletions(-)
+
+--- a/sound/drivers/aloop.c
++++ b/sound/drivers/aloop.c
+@@ -39,6 +39,7 @@
+ #include <sound/core.h>
+ #include <sound/control.h>
+ #include <sound/pcm.h>
++#include <sound/pcm_params.h>
+ #include <sound/info.h>
+ #include <sound/initval.h>
+@@ -622,14 +623,12 @@ static int rule_format(struct snd_pcm_hw
+ {
+       struct snd_pcm_hardware *hw = rule->private;
+-      struct snd_mask *maskp = hw_param_mask(params, rule->var);
++      struct snd_mask m;
+-      maskp->bits[0] &= (u_int32_t)hw->formats;
+-      maskp->bits[1] &= (u_int32_t)(hw->formats >> 32);
+-      memset(maskp->bits + 2, 0, (SNDRV_MASK_MAX-64) / 8); /* clear rest */
+-      if (! maskp->bits[0] && ! maskp->bits[1])
+-              return -EINVAL;
+-      return 0;
++      snd_mask_none(&m);
++      m.bits[0] = (u_int32_t)hw->formats;
++      m.bits[1] = (u_int32_t)(hw->formats >> 32);
++      return snd_mask_refine(hw_param_mask(params, rule->var), &m);
+ }
+ static int rule_rate(struct snd_pcm_hw_params *params,
diff --git a/queue-4.4/alsa-aloop-fix-racy-hw-constraints-adjustment.patch b/queue-4.4/alsa-aloop-fix-racy-hw-constraints-adjustment.patch
new file mode 100644 (file)
index 0000000..c1bbdf3
--- /dev/null
@@ -0,0 +1,149 @@
+From 898dfe4687f460ba337a01c11549f87269a13fa2 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Thu, 4 Jan 2018 17:38:54 +0100
+Subject: ALSA: aloop: Fix racy hw constraints adjustment
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 898dfe4687f460ba337a01c11549f87269a13fa2 upstream.
+
+The aloop driver tries to update the hw constraints of the connected
+target on the cable of the opened PCM substream.  This is done by
+adding the extra hw constraints rules referring to the substream
+runtime->hw fields, while the other substream may update the runtime
+hw of another side on the fly.
+
+This is, however, racy and may result in the inconsistent values when
+both PCM streams perform the prepare concurrently.  One of the reason
+is that it overwrites the other's runtime->hw field; which is not only
+racy but also broken when it's called before the open of another side
+finishes.  And, since the reference to runtime->hw isn't protected,
+the concurrent write may give the partial value update and become
+inconsistent.
+
+This patch is an attempt to fix and clean up:
+- The prepare doesn't change the runtime->hw of other side any longer,
+  but only update the cable->hw that is referred commonly.
+- The extra rules refer to the loopback_pcm object instead of the
+  runtime->hw.  The actual hw is deduced from cable->hw.
+- The extra rules take the cable_lock to protect against the race.
+
+Fixes: b1c73fc8e697 ("ALSA: snd-aloop: Fix hw_params restrictions and checking")
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/drivers/aloop.c |   51 ++++++++++++++++++++------------------------------
+ 1 file changed, 21 insertions(+), 30 deletions(-)
+
+--- a/sound/drivers/aloop.c
++++ b/sound/drivers/aloop.c
+@@ -306,19 +306,6 @@ static int loopback_trigger(struct snd_p
+       return 0;
+ }
+-static void params_change_substream(struct loopback_pcm *dpcm,
+-                                  struct snd_pcm_runtime *runtime)
+-{
+-      struct snd_pcm_runtime *dst_runtime;
+-
+-      if (dpcm == NULL || dpcm->substream == NULL)
+-              return;
+-      dst_runtime = dpcm->substream->runtime;
+-      if (dst_runtime == NULL)
+-              return;
+-      dst_runtime->hw = dpcm->cable->hw;
+-}
+-
+ static void params_change(struct snd_pcm_substream *substream)
+ {
+       struct snd_pcm_runtime *runtime = substream->runtime;
+@@ -330,10 +317,6 @@ static void params_change(struct snd_pcm
+       cable->hw.rate_max = runtime->rate;
+       cable->hw.channels_min = runtime->channels;
+       cable->hw.channels_max = runtime->channels;
+-      params_change_substream(cable->streams[SNDRV_PCM_STREAM_PLAYBACK],
+-                              runtime);
+-      params_change_substream(cable->streams[SNDRV_PCM_STREAM_CAPTURE],
+-                              runtime);
+ }
+ static int loopback_prepare(struct snd_pcm_substream *substream)
+@@ -621,24 +604,29 @@ static unsigned int get_cable_index(stru
+ static int rule_format(struct snd_pcm_hw_params *params,
+                      struct snd_pcm_hw_rule *rule)
+ {
+-
+-      struct snd_pcm_hardware *hw = rule->private;
++      struct loopback_pcm *dpcm = rule->private;
++      struct loopback_cable *cable = dpcm->cable;
+       struct snd_mask m;
+       snd_mask_none(&m);
+-      m.bits[0] = (u_int32_t)hw->formats;
+-      m.bits[1] = (u_int32_t)(hw->formats >> 32);
++      mutex_lock(&dpcm->loopback->cable_lock);
++      m.bits[0] = (u_int32_t)cable->hw.formats;
++      m.bits[1] = (u_int32_t)(cable->hw.formats >> 32);
++      mutex_unlock(&dpcm->loopback->cable_lock);
+       return snd_mask_refine(hw_param_mask(params, rule->var), &m);
+ }
+ static int rule_rate(struct snd_pcm_hw_params *params,
+                    struct snd_pcm_hw_rule *rule)
+ {
+-      struct snd_pcm_hardware *hw = rule->private;
++      struct loopback_pcm *dpcm = rule->private;
++      struct loopback_cable *cable = dpcm->cable;
+       struct snd_interval t;
+-        t.min = hw->rate_min;
+-        t.max = hw->rate_max;
++      mutex_lock(&dpcm->loopback->cable_lock);
++      t.min = cable->hw.rate_min;
++      t.max = cable->hw.rate_max;
++      mutex_unlock(&dpcm->loopback->cable_lock);
+         t.openmin = t.openmax = 0;
+         t.integer = 0;
+       return snd_interval_refine(hw_param_interval(params, rule->var), &t);
+@@ -647,11 +635,14 @@ static int rule_rate(struct snd_pcm_hw_p
+ static int rule_channels(struct snd_pcm_hw_params *params,
+                        struct snd_pcm_hw_rule *rule)
+ {
+-      struct snd_pcm_hardware *hw = rule->private;
++      struct loopback_pcm *dpcm = rule->private;
++      struct loopback_cable *cable = dpcm->cable;
+       struct snd_interval t;
+-        t.min = hw->channels_min;
+-        t.max = hw->channels_max;
++      mutex_lock(&dpcm->loopback->cable_lock);
++      t.min = cable->hw.channels_min;
++      t.max = cable->hw.channels_max;
++      mutex_unlock(&dpcm->loopback->cable_lock);
+         t.openmin = t.openmax = 0;
+         t.integer = 0;
+       return snd_interval_refine(hw_param_interval(params, rule->var), &t);
+@@ -717,19 +708,19 @@ static int loopback_open(struct snd_pcm_
+       /* are cached -> they do not reflect the actual state */
+       err = snd_pcm_hw_rule_add(runtime, 0,
+                                 SNDRV_PCM_HW_PARAM_FORMAT,
+-                                rule_format, &runtime->hw,
++                                rule_format, dpcm,
+                                 SNDRV_PCM_HW_PARAM_FORMAT, -1);
+       if (err < 0)
+               goto unlock;
+       err = snd_pcm_hw_rule_add(runtime, 0,
+                                 SNDRV_PCM_HW_PARAM_RATE,
+-                                rule_rate, &runtime->hw,
++                                rule_rate, dpcm,
+                                 SNDRV_PCM_HW_PARAM_RATE, -1);
+       if (err < 0)
+               goto unlock;
+       err = snd_pcm_hw_rule_add(runtime, 0,
+                                 SNDRV_PCM_HW_PARAM_CHANNELS,
+-                                rule_channels, &runtime->hw,
++                                rule_channels, dpcm,
+                                 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+       if (err < 0)
+               goto unlock;
diff --git a/queue-4.4/alsa-aloop-release-cable-upon-open-error-path.patch b/queue-4.4/alsa-aloop-release-cable-upon-open-error-path.patch
new file mode 100644 (file)
index 0000000..0866a57
--- /dev/null
@@ -0,0 +1,102 @@
+From 9685347aa0a5c2869058ca6ab79fd8e93084a67f Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Fri, 5 Jan 2018 16:09:47 +0100
+Subject: ALSA: aloop: Release cable upon open error path
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 9685347aa0a5c2869058ca6ab79fd8e93084a67f upstream.
+
+The aloop runtime object and its assignment in the cable are left even
+when opening a substream fails.  This doesn't mean any memory leak,
+but it still keeps the invalid pointer that may be referred by the
+another side of the cable spontaneously, which is a potential Oops
+cause.
+
+Clean up the cable assignment and the empty cable upon the error path
+properly.
+
+Fixes: 597603d615d2 ("ALSA: introduce the snd-aloop module for the PCM loopback")
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/drivers/aloop.c |   38 +++++++++++++++++++++++++-------------
+ 1 file changed, 25 insertions(+), 13 deletions(-)
+
+--- a/sound/drivers/aloop.c
++++ b/sound/drivers/aloop.c
+@@ -658,12 +658,31 @@ static int rule_channels(struct snd_pcm_
+       return snd_interval_refine(hw_param_interval(params, rule->var), &t);
+ }
++static void free_cable(struct snd_pcm_substream *substream)
++{
++      struct loopback *loopback = substream->private_data;
++      int dev = get_cable_index(substream);
++      struct loopback_cable *cable;
++
++      cable = loopback->cables[substream->number][dev];
++      if (!cable)
++              return;
++      if (cable->streams[!substream->stream]) {
++              /* other stream is still alive */
++              cable->streams[substream->stream] = NULL;
++      } else {
++              /* free the cable */
++              loopback->cables[substream->number][dev] = NULL;
++              kfree(cable);
++      }
++}
++
+ static int loopback_open(struct snd_pcm_substream *substream)
+ {
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct loopback *loopback = substream->private_data;
+       struct loopback_pcm *dpcm;
+-      struct loopback_cable *cable;
++      struct loopback_cable *cable = NULL;
+       int err = 0;
+       int dev = get_cable_index(substream);
+@@ -682,7 +701,6 @@ static int loopback_open(struct snd_pcm_
+       if (!cable) {
+               cable = kzalloc(sizeof(*cable), GFP_KERNEL);
+               if (!cable) {
+-                      kfree(dpcm);
+                       err = -ENOMEM;
+                       goto unlock;
+               }
+@@ -724,6 +742,10 @@ static int loopback_open(struct snd_pcm_
+       else
+               runtime->hw = cable->hw;
+  unlock:
++      if (err < 0) {
++              free_cable(substream);
++              kfree(dpcm);
++      }
+       mutex_unlock(&loopback->cable_lock);
+       return err;
+ }
+@@ -732,20 +754,10 @@ static int loopback_close(struct snd_pcm
+ {
+       struct loopback *loopback = substream->private_data;
+       struct loopback_pcm *dpcm = substream->runtime->private_data;
+-      struct loopback_cable *cable;
+-      int dev = get_cable_index(substream);
+       loopback_timer_stop(dpcm);
+       mutex_lock(&loopback->cable_lock);
+-      cable = loopback->cables[substream->number][dev];
+-      if (cable->streams[!substream->stream]) {
+-              /* other stream is still alive */
+-              cable->streams[substream->stream] = NULL;
+-      } else {
+-              /* free the cable */
+-              loopback->cables[substream->number][dev] = NULL;
+-              kfree(cable);
+-      }
++      free_cable(substream);
+       mutex_unlock(&loopback->cable_lock);
+       return 0;
+ }
diff --git a/queue-4.4/alsa-pcm-abort-properly-at-pending-signal-in-oss-read-write-loops.patch b/queue-4.4/alsa-pcm-abort-properly-at-pending-signal-in-oss-read-write-loops.patch
new file mode 100644 (file)
index 0000000..4b1a3ad
--- /dev/null
@@ -0,0 +1,50 @@
+From 29159a4ed7044c52e3e2cf1a9fb55cec4745c60b Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 8 Jan 2018 13:58:31 +0100
+Subject: ALSA: pcm: Abort properly at pending signal in OSS read/write loops
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 29159a4ed7044c52e3e2cf1a9fb55cec4745c60b upstream.
+
+The loops for read and write in PCM OSS emulation have no proper check
+of pending signals, and they keep processing even after user tries to
+break.  This results in a very long delay, often seen as RCU stall
+when a huge unprocessed bytes remain queued.  The bug could be easily
+triggered by syzkaller.
+
+As a simple workaround, this patch adds the proper check of pending
+signals and aborts the loop appropriately.
+
+Reported-by: syzbot+993cb4cfcbbff3947c21@syzkaller.appspotmail.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/oss/pcm_oss.c |    8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/sound/core/oss/pcm_oss.c
++++ b/sound/core/oss/pcm_oss.c
+@@ -1416,6 +1416,10 @@ static ssize_t snd_pcm_oss_write1(struct
+                           tmp != runtime->oss.period_bytes)
+                               break;
+               }
++              if (signal_pending(current)) {
++                      tmp = -ERESTARTSYS;
++                      goto err;
++              }
+       }
+       mutex_unlock(&runtime->oss.params_lock);
+       return xfer;
+@@ -1501,6 +1505,10 @@ static ssize_t snd_pcm_oss_read1(struct
+                       bytes -= tmp;
+                       xfer += tmp;
+               }
++              if (signal_pending(current)) {
++                      tmp = -ERESTARTSYS;
++                      goto err;
++              }
+       }
+       mutex_unlock(&runtime->oss.params_lock);
+       return xfer;
diff --git a/queue-4.4/alsa-pcm-add-missing-error-checks-in-oss-emulation-plugin-builder.patch b/queue-4.4/alsa-pcm-add-missing-error-checks-in-oss-emulation-plugin-builder.patch
new file mode 100644 (file)
index 0000000..7b4a055
--- /dev/null
@@ -0,0 +1,54 @@
+From 6708913750344a900f2e73bfe4a4d6dbbce4fe8d Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Thu, 4 Jan 2018 16:39:27 +0100
+Subject: ALSA: pcm: Add missing error checks in OSS emulation plugin builder
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 6708913750344a900f2e73bfe4a4d6dbbce4fe8d upstream.
+
+In the OSS emulation plugin builder where the frame size is parsed in
+the plugin chain, some places miss the possible errors returned from
+the plugin src_ or dst_frames callback.
+
+This patch papers over such places.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/oss/pcm_plugin.c |   14 +++++++++++---
+ 1 file changed, 11 insertions(+), 3 deletions(-)
+
+--- a/sound/core/oss/pcm_plugin.c
++++ b/sound/core/oss/pcm_plugin.c
+@@ -591,18 +591,26 @@ snd_pcm_sframes_t snd_pcm_plug_write_tra
+       snd_pcm_sframes_t frames = size;
+       plugin = snd_pcm_plug_first(plug);
+-      while (plugin && frames > 0) {
++      while (plugin) {
++              if (frames <= 0)
++                      return frames;
+               if ((next = plugin->next) != NULL) {
+                       snd_pcm_sframes_t frames1 = frames;
+-                      if (plugin->dst_frames)
++                      if (plugin->dst_frames) {
+                               frames1 = plugin->dst_frames(plugin, frames);
++                              if (frames1 <= 0)
++                                      return frames1;
++                      }
+                       if ((err = next->client_channels(next, frames1, &dst_channels)) < 0) {
+                               return err;
+                       }
+                       if (err != frames1) {
+                               frames = err;
+-                              if (plugin->src_frames)
++                              if (plugin->src_frames) {
+                                       frames = plugin->src_frames(plugin, frames1);
++                                      if (frames <= 0)
++                                              return frames;
++                              }
+                       }
+               } else
+                       dst_channels = NULL;
diff --git a/queue-4.4/alsa-pcm-allow-aborting-mutex-lock-at-oss-read-write-loops.patch b/queue-4.4/alsa-pcm-allow-aborting-mutex-lock-at-oss-read-write-loops.patch
new file mode 100644 (file)
index 0000000..7ea6408
--- /dev/null
@@ -0,0 +1,103 @@
+From 900498a34a3ac9c611e9b425094c8106bdd7dc1c Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 8 Jan 2018 14:03:53 +0100
+Subject: ALSA: pcm: Allow aborting mutex lock at OSS read/write loops
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 900498a34a3ac9c611e9b425094c8106bdd7dc1c upstream.
+
+PCM OSS read/write loops keep taking the mutex lock for the whole
+read/write, and this might take very long when the exceptionally high
+amount of data is given.  Also, since it invokes with mutex_lock(),
+the concurrent read/write becomes unbreakable.
+
+This patch tries to address these issues by replacing mutex_lock()
+with mutex_lock_interruptible(), and also splits / re-takes the lock
+at each read/write period chunk, so that it can switch the context
+more finely if requested.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/oss/pcm_oss.c |   36 +++++++++++++++++++++---------------
+ 1 file changed, 21 insertions(+), 15 deletions(-)
+
+--- a/sound/core/oss/pcm_oss.c
++++ b/sound/core/oss/pcm_oss.c
+@@ -1369,8 +1369,11 @@ static ssize_t snd_pcm_oss_write1(struct
+       if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)
+               return tmp;
+-      mutex_lock(&runtime->oss.params_lock);
+       while (bytes > 0) {
++              if (mutex_lock_interruptible(&runtime->oss.params_lock)) {
++                      tmp = -ERESTARTSYS;
++                      break;
++              }
+               if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) {
+                       tmp = bytes;
+                       if (tmp + runtime->oss.buffer_used > runtime->oss.period_bytes)
+@@ -1414,18 +1417,18 @@ static ssize_t snd_pcm_oss_write1(struct
+                       xfer += tmp;
+                       if ((substream->f_flags & O_NONBLOCK) != 0 &&
+                           tmp != runtime->oss.period_bytes)
+-                              break;
++                              tmp = -EAGAIN;
+               }
++ err:
++              mutex_unlock(&runtime->oss.params_lock);
++              if (tmp < 0)
++                      break;
+               if (signal_pending(current)) {
+                       tmp = -ERESTARTSYS;
+-                      goto err;
++                      break;
+               }
++              tmp = 0;
+       }
+-      mutex_unlock(&runtime->oss.params_lock);
+-      return xfer;
+-
+- err:
+-      mutex_unlock(&runtime->oss.params_lock);
+       return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
+ }
+@@ -1473,8 +1476,11 @@ static ssize_t snd_pcm_oss_read1(struct
+       if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)
+               return tmp;
+-      mutex_lock(&runtime->oss.params_lock);
+       while (bytes > 0) {
++              if (mutex_lock_interruptible(&runtime->oss.params_lock)) {
++                      tmp = -ERESTARTSYS;
++                      break;
++              }
+               if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) {
+                       if (runtime->oss.buffer_used == 0) {
+                               tmp = snd_pcm_oss_read2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1);
+@@ -1505,16 +1511,16 @@ static ssize_t snd_pcm_oss_read1(struct
+                       bytes -= tmp;
+                       xfer += tmp;
+               }
++ err:
++              mutex_unlock(&runtime->oss.params_lock);
++              if (tmp < 0)
++                      break;
+               if (signal_pending(current)) {
+                       tmp = -ERESTARTSYS;
+-                      goto err;
++                      break;
+               }
++              tmp = 0;
+       }
+-      mutex_unlock(&runtime->oss.params_lock);
+-      return xfer;
+-
+- err:
+-      mutex_unlock(&runtime->oss.params_lock);
+       return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
+ }
diff --git a/queue-4.4/alsa-pcm-remove-incorrect-snd_bug_on-usages.patch b/queue-4.4/alsa-pcm-remove-incorrect-snd_bug_on-usages.patch
new file mode 100644 (file)
index 0000000..ab0f059
--- /dev/null
@@ -0,0 +1,77 @@
+From fe08f34d066f4404934a509b6806db1a4f700c86 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 1 Jan 2018 09:50:50 +0100
+Subject: ALSA: pcm: Remove incorrect snd_BUG_ON() usages
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit fe08f34d066f4404934a509b6806db1a4f700c86 upstream.
+
+syzkaller triggered kernel warnings through PCM OSS emulation at
+closing a stream:
+  WARNING: CPU: 0 PID: 3502 at sound/core/pcm_lib.c:1635
+  snd_pcm_hw_param_first+0x289/0x690 sound/core/pcm_lib.c:1635
+  Call Trace:
+  ....
+   snd_pcm_hw_param_near.constprop.27+0x78d/0x9a0 sound/core/oss/pcm_oss.c:457
+   snd_pcm_oss_change_params+0x17d3/0x3720 sound/core/oss/pcm_oss.c:969
+   snd_pcm_oss_make_ready+0xaa/0x130 sound/core/oss/pcm_oss.c:1128
+   snd_pcm_oss_sync+0x257/0x830 sound/core/oss/pcm_oss.c:1638
+   snd_pcm_oss_release+0x20b/0x280 sound/core/oss/pcm_oss.c:2431
+   __fput+0x327/0x7e0 fs/file_table.c:210
+   ....
+
+This happens while it tries to open and set up the aloop device
+concurrently.  The warning above (invoked from snd_BUG_ON() macro) is
+to detect the unexpected logical error where snd_pcm_hw_refine() call
+shouldn't fail.  The theory is true for the case where the hw_params
+config rules are static.  But for an aloop device, the hw_params rule
+condition does vary dynamically depending on the connected target;
+when another device is opened and changes the parameters, the device
+connected in another side is also affected, and it caused the error
+from snd_pcm_hw_refine().
+
+That is, the simplest "solution" for this is to remove the incorrect
+assumption of static rules, and treat such an error as a normal error
+path.  As there are a couple of other places using snd_BUG_ON()
+incorrectly, this patch removes these spurious snd_BUG_ON() calls.
+
+Reported-by: syzbot+6f11c7e2a1b91d466432@syzkaller.appspotmail.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/oss/pcm_oss.c |    1 -
+ sound/core/pcm_lib.c     |    4 ++--
+ 2 files changed, 2 insertions(+), 3 deletions(-)
+
+--- a/sound/core/oss/pcm_oss.c
++++ b/sound/core/oss/pcm_oss.c
+@@ -465,7 +465,6 @@ static int snd_pcm_hw_param_near(struct
+               v = snd_pcm_hw_param_last(pcm, params, var, dir);
+       else
+               v = snd_pcm_hw_param_first(pcm, params, var, dir);
+-      snd_BUG_ON(v < 0);
+       return v;
+ }
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -1664,7 +1664,7 @@ int snd_pcm_hw_param_first(struct snd_pc
+               return changed;
+       if (params->rmask) {
+               int err = snd_pcm_hw_refine(pcm, params);
+-              if (snd_BUG_ON(err < 0))
++              if (err < 0)
+                       return err;
+       }
+       return snd_pcm_hw_param_value(params, var, dir);
+@@ -1711,7 +1711,7 @@ int snd_pcm_hw_param_last(struct snd_pcm
+               return changed;
+       if (params->rmask) {
+               int err = snd_pcm_hw_refine(pcm, params);
+-              if (snd_BUG_ON(err < 0))
++              if (err < 0)
+                       return err;
+       }
+       return snd_pcm_hw_param_value(params, var, dir);
diff --git a/queue-4.4/nvmem-add-i.mx7-support-to-snvs-lpgpr.patch b/queue-4.4/nvmem-add-i.mx7-support-to-snvs-lpgpr.patch
new file mode 100644 (file)
index 0000000..6fde003
--- /dev/null
@@ -0,0 +1,143 @@
+From yurovsky@gmail.com  Thu Jan 11 07:36:10 2018
+From: Andrey Yurovsky <yurovsky@gmail.com>
+Date: Wed, 10 Jan 2018 15:47:34 -0800
+Subject: [PATCH] nvmem: add i.MX7 support to snvs-lpgpr
+To: srinivas.kandagatla@linaro.org
+Cc: Andrey Yurovsky <yurovsky@gmail.com>, o.rempel@pengutronix.de, gregkh@linuxfoundation.org
+Message-ID: <20180110234734.26213-1-yurovsky@gmail.com>
+
+
+The i.MX7 family has similar SNVS hardware so make the snvs-lpgpr
+support it along with the i.MX6 family. The register interface is the
+same except for the number and offset of the general purpose registers.
+
+Signed-off-by: Andrey Yurovsky <yurovsky@gmail.com>
+---
+ .../devicetree/bindings/nvmem/snvs-lpgpr.txt       |  3 ++-
+ drivers/nvmem/Kconfig                              |  4 ++--
+ drivers/nvmem/snvs_lpgpr.c                         | 27 +++++++++++++++++-----
+ 3 files changed, 25 insertions(+), 9 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/nvmem/snvs-lpgpr.txt b/Documentation/devicetree/bindings/nvmem/snvs-lpgpr.txt
+index 20bc49b49799..3cb170896658 100644
+--- a/Documentation/devicetree/bindings/nvmem/snvs-lpgpr.txt
++++ b/Documentation/devicetree/bindings/nvmem/snvs-lpgpr.txt
+@@ -1,5 +1,5 @@
+ Device tree bindings for Low Power General Purpose Register found in i.MX6Q/D
+-Secure Non-Volatile Storage.
++and i.MX7 Secure Non-Volatile Storage.
+ This DT node should be represented as a sub-node of a "syscon",
+ "simple-mfd" node.
+@@ -8,6 +8,7 @@ Required properties:
+ - compatible: should be one of the fallowing variants:
+       "fsl,imx6q-snvs-lpgpr" for Freescale i.MX6Q/D/DL/S
+       "fsl,imx6ul-snvs-lpgpr" for Freescale i.MX6UL
++      "fsl,imx7d-snvs-lpgpr" for Freescale i.MX7D/S
+ Example:
+ snvs: snvs@020cc000 {
+diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
+index ff505af064ba..5f9bc787d634 100644
+--- a/drivers/nvmem/Kconfig
++++ b/drivers/nvmem/Kconfig
+@@ -167,10 +167,10 @@ config MESON_MX_EFUSE
+ config NVMEM_SNVS_LPGPR
+       tristate "Support for Low Power General Purpose Register"
+-      depends on SOC_IMX6 || COMPILE_TEST
++      depends on SOC_IMX6 || SOC_IMX7D || COMPILE_TEST
+       help
+         This is a driver for Low Power General Purpose Register (LPGPR) available on
+-        i.MX6 SoCs in Secure Non-Volatile Storage (SNVS) of this chip.
++        i.MX6 and i.MX7 SoCs in Secure Non-Volatile Storage (SNVS) of this chip.
+         This driver can also be built as a module. If so, the module
+         will be called nvmem-snvs-lpgpr.
+diff --git a/drivers/nvmem/snvs_lpgpr.c b/drivers/nvmem/snvs_lpgpr.c
+index e5c2a4a17f03..3ed617a16db0 100644
+--- a/drivers/nvmem/snvs_lpgpr.c
++++ b/drivers/nvmem/snvs_lpgpr.c
+@@ -14,15 +14,21 @@
+ #include <linux/regmap.h>
+ #define IMX6Q_SNVS_HPLR               0x00
+-#define IMX6Q_GPR_SL          BIT(5)
+ #define IMX6Q_SNVS_LPLR               0x34
+-#define IMX6Q_GPR_HL          BIT(5)
+ #define IMX6Q_SNVS_LPGPR      0x68
++#define IMX7D_SNVS_HPLR               0x00
++#define IMX7D_SNVS_LPLR               0x34
++#define IMX7D_SNVS_LPGPR      0x90
++
++#define IMX_GPR_SL            BIT(5)
++#define IMX_GPR_HL            BIT(5)
++
+ struct snvs_lpgpr_cfg {
+       int offset;
+       int offset_hplr;
+       int offset_lplr;
++      int size;
+ };
+ struct snvs_lpgpr_priv {
+@@ -36,6 +42,14 @@ static const struct snvs_lpgpr_cfg snvs_lpgpr_cfg_imx6q = {
+       .offset         = IMX6Q_SNVS_LPGPR,
+       .offset_hplr    = IMX6Q_SNVS_HPLR,
+       .offset_lplr    = IMX6Q_SNVS_LPLR,
++      .size           = 4,
++};
++
++static const struct snvs_lpgpr_cfg snvs_lpgpr_cfg_imx7d = {
++      .offset         = IMX7D_SNVS_LPGPR,
++      .offset_hplr    = IMX7D_SNVS_HPLR,
++      .offset_lplr    = IMX7D_SNVS_LPLR,
++      .size           = 16,
+ };
+ static int snvs_lpgpr_write(void *context, unsigned int offset, void *val,
+@@ -50,14 +64,14 @@ static int snvs_lpgpr_write(void *context, unsigned int offset, void *val,
+       if (ret < 0)
+               return ret;
+-      if (lock_reg & IMX6Q_GPR_SL)
++      if (lock_reg & IMX_GPR_SL)
+               return -EPERM;
+       ret = regmap_read(priv->regmap, dcfg->offset_lplr, &lock_reg);
+       if (ret < 0)
+               return ret;
+-      if (lock_reg & IMX6Q_GPR_HL)
++      if (lock_reg & IMX_GPR_HL)
+               return -EPERM;
+       return regmap_bulk_write(priv->regmap, dcfg->offset + offset, val,
+@@ -112,7 +126,7 @@ static int snvs_lpgpr_probe(struct platform_device *pdev)
+       cfg->dev = dev;
+       cfg->stride = 4,
+       cfg->word_size = 4,
+-      cfg->size = 4,
++      cfg->size = dcfg->size,
+       cfg->owner = THIS_MODULE,
+       cfg->reg_read  = snvs_lpgpr_read,
+       cfg->reg_write = snvs_lpgpr_write,
+@@ -137,6 +151,7 @@ static const struct of_device_id snvs_lpgpr_dt_ids[] = {
+       { .compatible = "fsl,imx6q-snvs-lpgpr", .data = &snvs_lpgpr_cfg_imx6q },
+       { .compatible = "fsl,imx6ul-snvs-lpgpr",
+         .data = &snvs_lpgpr_cfg_imx6q },
++      { .compatible = "fsl,imx7d-snvs-lpgpr", .data = &snvs_lpgpr_cfg_imx7d },
+       { },
+ };
+ MODULE_DEVICE_TABLE(of, snvs_lpgpr_dt_ids);
+@@ -152,5 +167,5 @@ static struct platform_driver snvs_lpgpr_driver = {
+ module_platform_driver(snvs_lpgpr_driver);
+ MODULE_AUTHOR("Oleksij Rempel <o.rempel@pengutronix.de>");
+-MODULE_DESCRIPTION("Low Power General Purpose Register in i.MX6 Secure Non-Volatile Storage");
++MODULE_DESCRIPTION("Low Power General Purpose Register in i.MX6 and i.MX7 Secure Non-Volatile Storage");
+ MODULE_LICENSE("GPL v2");
+-- 
+2.14.3
+
index 1ab6b421ad8e88174830d05f3904226143c44c40..5adce22d03f0b541eb240321e8246e3ef02ce173 100644 (file)
@@ -14,3 +14,11 @@ kvm-vmx-scrub-hardware-gprs-at-vm-exit.patch
 x86-vsdo-fix-build-on-paravirt_clock-y-kvm_guest-n.patch
 x86-acpi-handle-sci-interrupts-above-legacy-space-gracefully.patch
 iommu-arm-smmu-v3-don-t-free-page-table-ops-twice.patch
+alsa-pcm-remove-incorrect-snd_bug_on-usages.patch
+alsa-pcm-add-missing-error-checks-in-oss-emulation-plugin-builder.patch
+alsa-pcm-abort-properly-at-pending-signal-in-oss-read-write-loops.patch
+alsa-pcm-allow-aborting-mutex-lock-at-oss-read-write-loops.patch
+alsa-aloop-release-cable-upon-open-error-path.patch
+alsa-aloop-fix-inconsistent-format-due-to-incomplete-rule.patch
+alsa-aloop-fix-racy-hw-constraints-adjustment.patch
+nvmem-add-i.mx7-support-to-snvs-lpgpr.patch