--- /dev/null
+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,
--- /dev/null
+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;
--- /dev/null
+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;
+ }
--- /dev/null
+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
+@@ -1381,6 +1381,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;
+@@ -1466,6 +1470,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;
--- /dev/null
+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
+@@ -592,18 +592,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;
--- /dev/null
+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
+@@ -1334,8 +1334,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)
+@@ -1379,18 +1382,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;
+ }
+
+@@ -1438,8 +1441,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);
+@@ -1470,16 +1476,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;
+ }
+
--- /dev/null
+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
+@@ -455,7 +455,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
+@@ -1632,7 +1632,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);
+@@ -1678,7 +1678,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);
--- /dev/null
+From fb51f1cd06f9ced7b7085a2a4636375d520431ca Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 3 Jan 2018 15:16:30 +0100
+Subject: ALSA: pcm: Workaround for weird PulseAudio behavior on rewind error
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit fb51f1cd06f9ced7b7085a2a4636375d520431ca upstream.
+
+The commit 9027c4639ef1 ("ALSA: pcm: Call ack() whenever appl_ptr is
+updated") introduced the possible error code returned from the PCM
+rewind ioctl. Basically the change was for handling the indirect PCM
+more correctly, but ironically, it caused rather a side-effect:
+PulseAudio gets pissed off when receiving an error from rewind, throws
+everything away and stops processing further, resulting in the
+silence.
+
+It's clearly a failure in the application side, so the best would be
+to fix that bug in PA. OTOH, PA is mostly the only user of the rewind
+feature, so it's not good to slap the sole customer.
+
+This patch tries to mitigate the situation: instead of returning an
+error, now the rewind ioctl returns zero when the driver can't rewind.
+It indicates that no rewind was performed, so the behavior is
+consistent, at least.
+
+Fixes: 9027c4639ef1 ("ALSA: pcm: Call ack() whenever appl_ptr is updated")
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/pcm_native.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -2582,7 +2582,7 @@ static snd_pcm_sframes_t forward_appl_pt
+ return ret < 0 ? ret : frames;
+ }
+
+-/* decrease the appl_ptr; returns the processed frames or a negative error */
++/* decrease the appl_ptr; returns the processed frames or zero for error */
+ static snd_pcm_sframes_t rewind_appl_ptr(struct snd_pcm_substream *substream,
+ snd_pcm_uframes_t frames,
+ snd_pcm_sframes_t avail)
+@@ -2599,7 +2599,12 @@ static snd_pcm_sframes_t rewind_appl_ptr
+ if (appl_ptr < 0)
+ appl_ptr += runtime->boundary;
+ ret = pcm_lib_apply_appl_ptr(substream, appl_ptr);
+- return ret < 0 ? ret : frames;
++ /* NOTE: we return zero for errors because PulseAudio gets depressed
++ * upon receiving an error from rewind ioctl and stops processing
++ * any longer. Returning zero means that no rewind is done, so
++ * it's not absolutely wrong to answer like that.
++ */
++ return ret < 0 ? 0 : frames;
+ }
+
+ static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *substream,
iw_cxgb4-reflect-the-original-wr-opcode-in-drain-cqes.patch
iw_cxgb4-when-flushing-complete-all-wrs-in-a-chain.patch
x86-acpi-handle-sci-interrupts-above-legacy-space-gracefully.patch
+alsa-pcm-remove-incorrect-snd_bug_on-usages.patch
+alsa-pcm-workaround-for-weird-pulseaudio-behavior-on-rewind-error.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