Accepting request 395038 from home:tiwai:branches:multimedia:libs

- Backport various upstream fixes for PCM (bnc#979702):
  0001-pcm_plugin-fix-appl-pointer-not-correct-when-mmap_co.patch
  0002-pcm-Clean-up-error-paths-in-snd_pcm_plugin_-helpers.patch
  0003-pcm-Fallback-open-as-the-first-instance-for-dmix-co.patch
  0004-pcm-softvol-fix-conversion-of-TLVs-min_db-and-max_dB.patch
  0005-pcm-Fix-suspend-resume-regression-with-dmix-co.patch
  0006-pcm-dmix-Fix-doubly-resume-of-slave-PCM.patch

OBS-URL: https://build.opensuse.org/request/show/395038
OBS-URL: https://build.opensuse.org/package/show/multimedia:libs/alsa?expand=0&rev=196
This commit is contained in:
Takashi Iwai 2016-05-12 15:03:05 +00:00 committed by Git OBS Bridge
parent b6b02f55ac
commit 75216f4ef8
8 changed files with 654 additions and 0 deletions

View File

@ -0,0 +1,135 @@
From 7c424edd116e76eee6218a1e9a6ff6c4daaf2a4d Mon Sep 17 00:00:00 2001
From: Shengjiu Wang <shengjiu.wang@freescale.com>
Date: Wed, 6 Apr 2016 19:02:12 +0800
Subject: [PATCH] pcm_plugin: fix appl pointer not correct when mmap_commit()
return error
When snd_pcm_mmap_commit() return error, the appl pointer is also updated.
which cause the avail_update()'s result wrong.
This patch move the snd_pcm_mmap_appl_forward() to the place when
snd_pcm_mmap_commit() is successfully returned.
Signed-off-by: Shengjiu Wang <shengjiu.wang@freescale.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_plugin.c | 48 ++++++++++++++++++++++++++++++++----------------
1 file changed, 32 insertions(+), 16 deletions(-)
diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
index d007e8c8bd4a..940491dbc84b 100644
--- a/src/pcm/pcm_plugin.c
+++ b/src/pcm/pcm_plugin.c
@@ -279,18 +279,22 @@ static snd_pcm_sframes_t snd_pcm_plugin_write_areas(snd_pcm_t *pcm,
return -EPIPE;
}
snd_atomic_write_begin(&plugin->watom);
- snd_pcm_mmap_appl_forward(pcm, frames);
result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
if (result > 0 && (snd_pcm_uframes_t)result != slave_frames) {
snd_pcm_sframes_t res;
res = plugin->undo_write(pcm, slave_areas, slave_offset + result, slave_frames, slave_frames - result);
- if (res < 0)
+ if (res < 0) {
+ snd_atomic_write_end(&plugin->watom);
return xfer > 0 ? (snd_pcm_sframes_t)xfer : res;
+ }
frames -= res;
}
- snd_atomic_write_end(&plugin->watom);
- if (result <= 0)
+ if (result <= 0) {
+ snd_atomic_write_end(&plugin->watom);
return xfer > 0 ? (snd_pcm_sframes_t)xfer : result;
+ }
+ snd_pcm_mmap_appl_forward(pcm, frames);
+ snd_atomic_write_end(&plugin->watom);
offset += frames;
xfer += frames;
size -= frames;
@@ -325,19 +329,23 @@ static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm,
return -EPIPE;
}
snd_atomic_write_begin(&plugin->watom);
- snd_pcm_mmap_appl_forward(pcm, frames);
result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
if (result > 0 && (snd_pcm_uframes_t)result != slave_frames) {
snd_pcm_sframes_t res;
res = plugin->undo_read(slave, areas, offset, frames, slave_frames - result);
- if (res < 0)
+ if (res < 0) {
+ snd_atomic_write_end(&plugin->watom);
return xfer > 0 ? (snd_pcm_sframes_t)xfer : res;
+ }
frames -= res;
}
- snd_atomic_write_end(&plugin->watom);
- if (result <= 0)
+ if (result <= 0) {
+ snd_atomic_write_end(&plugin->watom);
return xfer > 0 ? (snd_pcm_sframes_t)xfer : result;
+ }
+ snd_pcm_mmap_appl_forward(pcm, frames);
+ snd_atomic_write_end(&plugin->watom);
offset += frames;
xfer += frames;
size -= frames;
@@ -423,19 +431,23 @@ snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm,
frames = plugin->write(pcm, areas, appl_offset, frames,
slave_areas, slave_offset, &slave_frames);
snd_atomic_write_begin(&plugin->watom);
- snd_pcm_mmap_appl_forward(pcm, frames);
result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
- snd_atomic_write_end(&plugin->watom);
if (result > 0 && (snd_pcm_uframes_t)result != slave_frames) {
snd_pcm_sframes_t res;
res = plugin->undo_write(pcm, slave_areas, slave_offset + result, slave_frames, slave_frames - result);
- if (res < 0)
+ if (res < 0) {
+ snd_atomic_write_end(&plugin->watom);
return xfer > 0 ? xfer : res;
+ }
frames -= res;
}
- if (result <= 0)
+ if (result <= 0) {
+ snd_atomic_write_end(&plugin->watom);
return xfer > 0 ? xfer : result;
+ }
+ snd_pcm_mmap_appl_forward(pcm, frames);
+ snd_atomic_write_end(&plugin->watom);
if (frames == cont)
appl_offset = 0;
else
@@ -490,19 +502,23 @@ static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
frames = (plugin->read)(pcm, areas, hw_offset, frames,
slave_areas, slave_offset, &slave_frames);
snd_atomic_write_begin(&plugin->watom);
- snd_pcm_mmap_hw_forward(pcm, frames);
result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
- snd_atomic_write_end(&plugin->watom);
if (result > 0 && (snd_pcm_uframes_t)result != slave_frames) {
snd_pcm_sframes_t res;
res = plugin->undo_read(slave, areas, hw_offset, frames, slave_frames - result);
- if (res < 0)
+ if (res < 0) {
+ snd_atomic_write_end(&plugin->watom);
return xfer > 0 ? (snd_pcm_sframes_t)xfer : res;
+ }
frames -= res;
}
- if (result <= 0)
+ if (result <= 0) {
+ snd_atomic_write_end(&plugin->watom);
return xfer > 0 ? (snd_pcm_sframes_t)xfer : result;
+ }
+ snd_pcm_mmap_hw_forward(pcm, frames);
+ snd_atomic_write_end(&plugin->watom);
if (frames == cont)
hw_offset = 0;
else
--
2.8.2

View File

@ -0,0 +1,213 @@
From 503a285ed60164d8c65c6ee9ba6f23631da753df Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 7 Apr 2016 16:29:41 +0200
Subject: [PATCH] pcm: Clean up error paths in snd_pcm_plugin_*() helpers
Minor code refactoring to unify the error return paths.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_plugin.c | 67 +++++++++++++++++++++++++++++++++++-----------------
1 file changed, 45 insertions(+), 22 deletions(-)
diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
index 940491dbc84b..8527783c3569 100644
--- a/src/pcm/pcm_plugin.c
+++ b/src/pcm/pcm_plugin.c
@@ -276,7 +276,8 @@ static snd_pcm_sframes_t snd_pcm_plugin_write_areas(snd_pcm_t *pcm,
if (CHECK_SANITY(slave_frames > snd_pcm_mmap_playback_avail(slave))) {
SNDMSG("write overflow %ld > %ld", slave_frames,
snd_pcm_mmap_playback_avail(slave));
- return -EPIPE;
+ err = -EPIPE;
+ goto error;
}
snd_atomic_write_begin(&plugin->watom);
result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
@@ -284,14 +285,14 @@ static snd_pcm_sframes_t snd_pcm_plugin_write_areas(snd_pcm_t *pcm,
snd_pcm_sframes_t res;
res = plugin->undo_write(pcm, slave_areas, slave_offset + result, slave_frames, slave_frames - result);
if (res < 0) {
- snd_atomic_write_end(&plugin->watom);
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : res;
+ err = res;
+ goto error_atomic;
}
frames -= res;
}
if (result <= 0) {
- snd_atomic_write_end(&plugin->watom);
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : result;
+ err = result;
+ goto error_atomic;
}
snd_pcm_mmap_appl_forward(pcm, frames);
snd_atomic_write_end(&plugin->watom);
@@ -300,6 +301,11 @@ static snd_pcm_sframes_t snd_pcm_plugin_write_areas(snd_pcm_t *pcm,
size -= frames;
}
return (snd_pcm_sframes_t)xfer;
+
+ error_atomic:
+ snd_atomic_write_end(&plugin->watom);
+ error:
+ return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
}
static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm,
@@ -311,6 +317,7 @@ static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm,
snd_pcm_t *slave = plugin->gen.slave;
snd_pcm_uframes_t xfer = 0;
snd_pcm_sframes_t result;
+ int err;
while (size > 0) {
snd_pcm_uframes_t frames = size;
@@ -326,7 +333,8 @@ static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm,
if (CHECK_SANITY(slave_frames > snd_pcm_mmap_capture_avail(slave))) {
SNDMSG("read overflow %ld > %ld", slave_frames,
snd_pcm_mmap_playback_avail(slave));
- return -EPIPE;
+ err = -EPIPE;
+ goto error;
}
snd_atomic_write_begin(&plugin->watom);
result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
@@ -335,14 +343,14 @@ static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm,
res = plugin->undo_read(slave, areas, offset, frames, slave_frames - result);
if (res < 0) {
- snd_atomic_write_end(&plugin->watom);
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : res;
+ err = res;
+ goto error_atomic;
}
frames -= res;
}
if (result <= 0) {
- snd_atomic_write_end(&plugin->watom);
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : result;
+ err = result;
+ goto error_atomic;
}
snd_pcm_mmap_appl_forward(pcm, frames);
snd_atomic_write_end(&plugin->watom);
@@ -351,6 +359,11 @@ static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm,
size -= frames;
}
return (snd_pcm_sframes_t)xfer;
+
+ error_atomic:
+ snd_atomic_write_end(&plugin->watom);
+ error:
+ return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
}
@@ -401,6 +414,7 @@ snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm,
snd_pcm_uframes_t appl_offset;
snd_pcm_sframes_t slave_size;
snd_pcm_sframes_t xfer;
+ int err;
if (pcm->stream == SND_PCM_STREAM_CAPTURE) {
snd_atomic_write_begin(&plugin->watom);
@@ -421,11 +435,10 @@ snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm,
snd_pcm_uframes_t slave_offset;
snd_pcm_uframes_t slave_frames = ULONG_MAX;
snd_pcm_sframes_t result;
- int err;
err = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
if (err < 0)
- return xfer > 0 ? xfer : err;
+ goto error;
if (frames > cont)
frames = cont;
frames = plugin->write(pcm, areas, appl_offset, frames,
@@ -437,14 +450,14 @@ snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm,
res = plugin->undo_write(pcm, slave_areas, slave_offset + result, slave_frames, slave_frames - result);
if (res < 0) {
- snd_atomic_write_end(&plugin->watom);
- return xfer > 0 ? xfer : res;
+ err = res;
+ goto error_atomic;
}
frames -= res;
}
if (result <= 0) {
- snd_atomic_write_end(&plugin->watom);
- return xfer > 0 ? xfer : result;
+ err = result;
+ goto error_atomic;
}
snd_pcm_mmap_appl_forward(pcm, frames);
snd_atomic_write_end(&plugin->watom);
@@ -461,6 +474,11 @@ snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm,
return -EPIPE;
}
return xfer;
+
+ error_atomic:
+ snd_atomic_write_end(&plugin->watom);
+ error:
+ return xfer > 0 ? xfer : err;
}
static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
@@ -468,6 +486,7 @@ static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
snd_pcm_plugin_t *plugin = pcm->private_data;
snd_pcm_t *slave = plugin->gen.slave;
snd_pcm_sframes_t slave_size;
+ int err;
slave_size = snd_pcm_avail_update(slave);
if (pcm->stream == SND_PCM_STREAM_CAPTURE &&
@@ -492,11 +511,10 @@ static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
snd_pcm_uframes_t slave_offset;
snd_pcm_uframes_t slave_frames = ULONG_MAX;
snd_pcm_sframes_t result;
- int err;
err = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
if (err < 0)
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
+ goto error;
if (frames > cont)
frames = cont;
frames = (plugin->read)(pcm, areas, hw_offset, frames,
@@ -508,14 +526,14 @@ static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
res = plugin->undo_read(slave, areas, hw_offset, frames, slave_frames - result);
if (res < 0) {
- snd_atomic_write_end(&plugin->watom);
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : res;
+ err = res;
+ goto error_atomic;
}
frames -= res;
}
if (result <= 0) {
- snd_atomic_write_end(&plugin->watom);
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : result;
+ err = result;
+ goto error_atomic;
}
snd_pcm_mmap_hw_forward(pcm, frames);
snd_atomic_write_end(&plugin->watom);
@@ -528,6 +546,11 @@ static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
xfer += frames;
}
return (snd_pcm_sframes_t)xfer;
+
+ error_atomic:
+ snd_atomic_write_end(&plugin->watom);
+ error:
+ return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
}
}
--
2.8.2

View File

@ -0,0 +1,106 @@
From fdba9e1bad8f769a6137e565471f0227f23a3132 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 14 Apr 2016 17:33:03 +0200
Subject: [PATCH] pcm: Fallback open as the first instance for dmix & co
dmix and other PCM plugins tries to open a secondary stream with
O_APPEND flag when the shmem was already attached by another.
However, when another streams have been already closed after the
shmem check, this open may return the error EBADFD, since the kernel
accepts O_APPEND only for the secondary streams.
This patch adds a workaround for such a case. It just retries opening
the stream as the first instance (i.e. without O_APPEND flag).
This is basically safe behavior (the kernel takes care of races), even
we may do this even unconditionally. But it's bad from the
performance POV, so we do it only when really needed.
Reported-by: Lars Lindqvist <lars.lindqvist@yandex.ru>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_dmix.c | 8 ++++++++
src/pcm/pcm_dshare.c | 8 ++++++++
src/pcm/pcm_dsnoop.c | 8 ++++++++
3 files changed, 24 insertions(+)
diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c
index b26a5c790e7e..007d35664ce7 100644
--- a/src/pcm/pcm_dmix.c
+++ b/src/pcm/pcm_dmix.c
@@ -1020,6 +1020,7 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
dmix->max_periods = opts->max_periods;
dmix->sync_ptr = snd_pcm_dmix_sync_ptr;
+ retry:
if (first_instance) {
/* recursion is already checked in
snd_pcm_direct_get_slave_ipc_offset() */
@@ -1076,6 +1077,13 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
SND_PCM_APPEND,
NULL);
if (ret < 0) {
+ /* all other streams have been closed;
+ * retry as the first instance
+ */
+ if (ret == -EBADFD) {
+ first_instance = 1;
+ goto retry;
+ }
SNDERR("unable to open slave");
goto _err;
}
diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c
index 58e47bbeac67..adb3587a2869 100644
--- a/src/pcm/pcm_dshare.c
+++ b/src/pcm/pcm_dshare.c
@@ -690,6 +690,7 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name,
break;
}
+ retry:
first_instance = ret = snd_pcm_direct_shm_create_or_connect(dshare);
if (ret < 0) {
SNDERR("unable to create IPC shm instance");
@@ -758,6 +759,13 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name,
SND_PCM_APPEND,
NULL);
if (ret < 0) {
+ /* all other streams have been closed;
+ * retry as the first instance
+ */
+ if (ret == -EBADFD) {
+ first_instance = 1;
+ goto retry;
+ }
SNDERR("unable to open slave");
goto _err;
}
diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c
index 576c35b111cd..8ff0ba57cb14 100644
--- a/src/pcm/pcm_dsnoop.c
+++ b/src/pcm/pcm_dsnoop.c
@@ -583,6 +583,7 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name,
break;
}
+ retry:
first_instance = ret = snd_pcm_direct_shm_create_or_connect(dsnoop);
if (ret < 0) {
SNDERR("unable to create IPC shm instance");
@@ -651,6 +652,13 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name,
SND_PCM_APPEND,
NULL);
if (ret < 0) {
+ /* all other streams have been closed;
+ * retry as the first instance
+ */
+ if (ret == -EBADFD) {
+ first_instance = 1;
+ goto retry;
+ }
SNDERR("unable to open slave");
goto _err;
}
--
2.8.2

View File

@ -0,0 +1,89 @@
From 85bf9915989e0a338632739684c75192c1753239 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rg=20Krause?= <joerg.krause@embedded.rocks>
Date: Sun, 8 May 2016 20:48:42 +0200
Subject: [PATCH] pcm: softvol: fix conversion of TLVs min_db and max_dB value
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Both, min_dB and max_dB, are floating type whereas the TLV is (always)
unsigned.
The problem with the conversion of a negative floating-point number into an
unsigned integer is, that the behavior is undefined. This may, depending on
the platform, result in a wrong TLV, i.e. for the default values of min_dB
(-51dB) and max_dB (0dB), alsactl generates the following state on an ARM
cpu build with GCC:
control.1 {
iface MIXER
name Master
value.0 255
value.1 255
comment {
access 'read write user'
type INTEGER
count 2
range '0 - 255'
tlv '00000001000000080000000000000014'
dbmin 0
dbmax 5100
dbvalue.0 5100
dbvalue.1 5100
}
}
With the fix applied, alsactl stores the correct TLV:
control.1 {
iface MIXER
name Master
value.0 255
value.1 255
comment {
access 'read write user'
type INTEGER
count 2
range '0 - 255'
tlv '0000000100000008ffffec1400000014'
dbmin -5100
dbmax 0
dbvalue.0 0
dbvalue.1 0
}
}
Also tested for different combinations of min_dB and max_dB other than the
default values.
Replaces:
http://mailman.alsa-project.org/pipermail/alsa-devel/2016-May/107733.html
Fixes:
http://mailman.alsa-project.org/pipermail/alsa-devel/2016-May/107628.html
Cc: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Jörg Krause <joerg.krause@embedded.rocks>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_softvol.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/pcm/pcm_softvol.c b/src/pcm/pcm_softvol.c
index 802aa4b7cb68..5492db8cf9f1 100644
--- a/src/pcm/pcm_softvol.c
+++ b/src/pcm/pcm_softvol.c
@@ -658,8 +658,8 @@ static int add_tlv_info(snd_pcm_softvol_t *svol, snd_ctl_elem_info_t *cinfo)
unsigned int tlv[4];
tlv[0] = SND_CTL_TLVT_DB_SCALE;
tlv[1] = 2 * sizeof(int);
- tlv[2] = svol->min_dB * 100;
- tlv[3] = (svol->max_dB - svol->min_dB) * 100 / svol->max_val;
+ tlv[2] = (int)(svol->min_dB * 100);
+ tlv[3] = (int)((svol->max_dB - svol->min_dB) * 100 / svol->max_val);
return snd_ctl_elem_tlv_write(svol->ctl, &cinfo->id, tlv);
}
--
2.8.2

View File

@ -0,0 +1,40 @@
From c14b0a08f0bf58e4f62307c68f8ff0137b4dec19 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 11 May 2016 09:06:47 +0200
Subject: [PATCH] pcm: Fix suspend/resume regression with dmix & co
The recent fix commit [8985742d91db: pcm: dmix: Handle slave PCM xrun
and unexpected states properly] caused a regression in dmix and other
plugins regarding suspend/resume. For example, aplay endlessly prints
"Suspended. Trying resume. Done." message if suspend and resume are
performed in the middle of playback.
The reason is that the commit above changed the shadow PCM state
(dmix->state) to SUSPENDED when the slave PCM is in suspend, while it
doesn't restore the shadow state upon resume. Thus it appears as if
it's always suspended even after the resume is invoked.
The fix is just to add the proper update of the shadow state in
snd_pcm_direct_resume().
Reported-by: Shengjiu Wang <shengjiu.wang@freescale.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_direct.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
index 14de734d98eb..e28738b0de96 100644
--- a/src/pcm/pcm_direct.c
+++ b/src/pcm/pcm_direct.c
@@ -848,6 +848,7 @@ int snd_pcm_direct_resume(snd_pcm_t *pcm)
snd_pcm_start(dmix->spcm);
err = 0;
}
+ dmix->state = snd_pcm_state(dmix->spcm);
snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
return err;
}
--
2.8.2

View File

@ -0,0 +1,48 @@
From 5610b356b5f110f7f8e586f56e5b74e0f0c2db38 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 11 May 2016 13:06:25 +0200
Subject: [PATCH] pcm: dmix: Fix doubly resume of slave PCM
The dmix plugin and co may trigger the resume for each instance in
snd_pcm_direct_resume(). It means that the slave PCM gets resumed or
re-prepared/started by each opened dmix stream, and this may end up
with the doubly triggers even though the slave PCM has been already
resumed by another dmix stream.
For avoiding this conflicts, check the slave PCM state and resume only
when it's still in the suspended state. Meanwhile we keep the shadow
state updated no matter whether the slave was triggered or not.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_direct.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
index e28738b0de96..ac082f1a73b2 100644
--- a/src/pcm/pcm_direct.c
+++ b/src/pcm/pcm_direct.c
@@ -841,6 +841,12 @@ int snd_pcm_direct_resume(snd_pcm_t *pcm)
int err;
snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
+ /* resume only when the slave PCM is still in suspended state */
+ if (snd_pcm_state(dmix->spcm) != SND_PCM_STATE_SUSPENDED) {
+ err = 0;
+ goto out;
+ }
+
err = snd_pcm_resume(dmix->spcm);
if (err == -ENOSYS) {
/* FIXME: error handling? */
@@ -848,6 +854,7 @@ int snd_pcm_direct_resume(snd_pcm_t *pcm)
snd_pcm_start(dmix->spcm);
err = 0;
}
+ out:
dmix->state = snd_pcm_state(dmix->spcm);
snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
return err;
--
2.8.2

View File

@ -1,3 +1,14 @@
-------------------------------------------------------------------
Thu May 12 14:44:48 CEST 2016 - tiwai@suse.de
- Backport various upstream fixes for PCM (bnc#979702):
0001-pcm_plugin-fix-appl-pointer-not-correct-when-mmap_co.patch
0002-pcm-Clean-up-error-paths-in-snd_pcm_plugin_-helpers.patch
0003-pcm-Fallback-open-as-the-first-instance-for-dmix-co.patch
0004-pcm-softvol-fix-conversion-of-TLVs-min_db-and-max_dB.patch
0005-pcm-Fix-suspend-resume-regression-with-dmix-co.patch
0006-pcm-dmix-Fix-doubly-resume-of-slave-PCM.patch
-------------------------------------------------------------------
Thu Mar 31 15:19:33 CEST 2016 - tiwai@suse.de

View File

@ -49,6 +49,12 @@ Source40: 50-alsa.conf
Source41: install-snd-module
# Patch: alsa-lib-git-fixes.diff
# upstream fixes
Patch1: 0001-pcm_plugin-fix-appl-pointer-not-correct-when-mmap_co.patch
Patch2: 0002-pcm-Clean-up-error-paths-in-snd_pcm_plugin_-helpers.patch
Patch3: 0003-pcm-Fallback-open-as-the-first-instance-for-dmix-co.patch
Patch4: 0004-pcm-softvol-fix-conversion-of-TLVs-min_db-and-max_dB.patch
Patch5: 0005-pcm-Fix-suspend-resume-regression-with-dmix-co.patch
Patch6: 0006-pcm-dmix-Fix-doubly-resume-of-slave-PCM.patch
# rest suse patches
Patch99: alsa-lib-doxygen-avoid-crash-for-11.3.diff
# suppress timestamp in documents
@ -119,6 +125,12 @@ Architecture.
%prep
%setup -q -n alsa-lib-%{package_version}
# %patch -p1
%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%patch5 -p1
%patch6 -p1
%if 0%{?suse_version} == 1130
%patch99 -p1
%endif