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

- Update to alsa-lib v1.1.2:
  * topology API updates
  * support of stacked async handlers
  * new UCM configs: rockchip-i2s, skylake-i2s, chtrt5645,
  * add cset-tlv ucm support
  * fix conversion of TLVs min_db and max_dB value in softvol
  * fix appl pointer in the error path of PCM plugin
  * PCM code cleanup
  * fix suspend/resume of PCM dmix, dsnoop and dshare plugins
  * fix doubly enumerated items via namehint
  * make PCM codes thread-safe
  * API documentation enhancements
  * element-set ctl API
  * Optimization by replacing alloca() usages
- Drop obsoleted patches:
  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
  0007-namehint-Don-t-enumerate-as-duplex-if-only-a-single-.patch
  0008-pcm-Define-namehint-for-single-directional-PCM-types.patch
  0009-conf-Add-thread-safe-global-tree-reference.patch
  0010-pcm-Remove-resume-support-from-dmix-co.patch
  0011-pcm-Fix-secondary-retry-in-dsnoop-and-dshare.patch
  0012-pcm-dmix-resume-workaround-for-buggy-driver.patch
  0013-pcm-dmix-Prepare-slave-when-it-s-in-SETUP-too.patch
  0014-pcm-dmix-Return-error-when-slave-is-in-OPEN-or-DISCO.patch
  0015-async-Handle-previously-installed-signal-handler.patch

OBS-URL: https://build.opensuse.org/request/show/416688
OBS-URL: https://build.opensuse.org/package/show/multimedia:libs/alsa?expand=0&rev=200
This commit is contained in:
Ismail Dönmez 2016-08-03 12:33:28 +00:00 committed by Git OBS Bridge
parent d51e946615
commit 9d21ad3488
20 changed files with 41 additions and 1560 deletions

View File

@ -1,135 +0,0 @@
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

@ -1,213 +0,0 @@
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

@ -1,106 +0,0 @@
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

@ -1,89 +0,0 @@
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

@ -1,40 +0,0 @@
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

@ -1,48 +0,0 @@
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,62 +0,0 @@
From 8cdbdae73109c901aec4984f6ba65e5b25722f13 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 12 May 2016 16:30:44 +0200
Subject: [PATCH 07/15] namehint: Don't enumerate as duplex if only a single
direction is defined
When a hint description has only either device_input or device_output,
we shouldn't handle it as a full duplex but rather a single
direction. In that way, we can avoid to list up a playback stream
like dmix or surround51 as a capture stream in the namehint.
Reported-by: Trent Reed <treed0803@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/control/namehint.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/src/control/namehint.c b/src/control/namehint.c
index 856957c76d74..ad8dda37a637 100644
--- a/src/control/namehint.c
+++ b/src/control/namehint.c
@@ -28,6 +28,7 @@
#include "local.h"
#ifndef DOC_HIDDEN
+#define DEV_SKIP 9999 /* some non-existing device number */
struct hint_list {
char **list;
unsigned int count;
@@ -90,7 +91,7 @@ static int get_dev_name1(struct hint_list *list, char **res, int device,
int stream)
{
*res = NULL;
- if (device < 0)
+ if (device < 0 || device == DEV_SKIP)
return 0;
switch (list->iface) {
#ifdef BUILD_HWDEP
@@ -317,7 +318,9 @@ static int try_config(snd_config_t *config,
err = -EINVAL;
goto __cleanup;
}
- list->device_output = -1;
+ /* skip the counterpart if only a single direction is defined */
+ if (list->device_output < 0)
+ list->device_output = DEV_SKIP;
}
if (snd_config_search(cfg, "device_output", &n) >= 0) {
if (snd_config_get_integer(n, &list->device_output) < 0) {
@@ -325,6 +328,9 @@ static int try_config(snd_config_t *config,
err = -EINVAL;
goto __cleanup;
}
+ /* skip the counterpart if only a single direction is defined */
+ if (list->device_input < 0)
+ list->device_input = DEV_SKIP;
}
} else if (level == 1 && !list->show_all)
goto __skip_add;
--
2.8.3

View File

@ -1,120 +0,0 @@
From 5fb3fe17249c3fffb8b8e15108ff72f27ba5e81c Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 12 May 2016 16:33:19 +0200
Subject: [PATCH 08/15] pcm: Define namehint for single directional PCM types
The PCM namehint for some PCM types like dmix, dsnoop and surround51
should be defined as single directional.
Reported-by: Trent Reed <treed0803@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/conf/pcm/dmix.conf | 2 +-
src/conf/pcm/dsnoop.conf | 2 +-
src/conf/pcm/surround21.conf | 2 +-
src/conf/pcm/surround40.conf | 2 +-
src/conf/pcm/surround41.conf | 2 +-
src/conf/pcm/surround50.conf | 2 +-
src/conf/pcm/surround51.conf | 2 +-
src/conf/pcm/surround71.conf | 2 +-
8 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/conf/pcm/dmix.conf b/src/conf/pcm/dmix.conf
index e62cb295278c..7d0aa0158c42 100644
--- a/src/conf/pcm/dmix.conf
+++ b/src/conf/pcm/dmix.conf
@@ -110,6 +110,6 @@ pcm.!dmix {
name defaults.namehint.extended
}
description "Direct sample mixing device"
- device $DEV
+ device_output $DEV
}
}
diff --git a/src/conf/pcm/dsnoop.conf b/src/conf/pcm/dsnoop.conf
index 49cfca98c262..abbd44f7fd79 100644
--- a/src/conf/pcm/dsnoop.conf
+++ b/src/conf/pcm/dsnoop.conf
@@ -110,6 +110,6 @@ pcm.!dsnoop {
name defaults.namehint.extended
}
description "Direct sample snooping device"
- device $DEV
+ device_input $DEV
}
}
diff --git a/src/conf/pcm/surround21.conf b/src/conf/pcm/surround21.conf
index 7f4676b3f714..1cf1b7af8dc6 100644
--- a/src/conf/pcm/surround21.conf
+++ b/src/conf/pcm/surround21.conf
@@ -56,6 +56,6 @@ pcm.!surround21 {
ttable.2.LFE 1
hint {
description "2.1 Surround output to Front and Subwoofer speakers"
- device $DEV
+ device_output $DEV
}
}
diff --git a/src/conf/pcm/surround40.conf b/src/conf/pcm/surround40.conf
index 361ccaa1e329..9788ad4884fd 100644
--- a/src/conf/pcm/surround40.conf
+++ b/src/conf/pcm/surround40.conf
@@ -54,6 +54,6 @@ pcm.!surround40 {
}
hint {
description "4.0 Surround output to Front and Rear speakers"
- device $DEV
+ device_output $DEV
}
}
diff --git a/src/conf/pcm/surround41.conf b/src/conf/pcm/surround41.conf
index 2f823815821a..7b4ef3beb43a 100644
--- a/src/conf/pcm/surround41.conf
+++ b/src/conf/pcm/surround41.conf
@@ -60,6 +60,6 @@ pcm.!surround41 {
ttable.4.LFE 1
hint {
description "4.1 Surround output to Front, Rear and Subwoofer speakers"
- device $DEV
+ device_output $DEV
}
}
diff --git a/src/conf/pcm/surround50.conf b/src/conf/pcm/surround50.conf
index dc95c179da68..7d9a9e798fd8 100644
--- a/src/conf/pcm/surround50.conf
+++ b/src/conf/pcm/surround50.conf
@@ -60,6 +60,6 @@ pcm.!surround50 {
ttable.4.FC 1
hint {
description "5.0 Surround output to Front, Center and Rear speakers"
- device $DEV
+ device_output $DEV
}
}
diff --git a/src/conf/pcm/surround51.conf b/src/conf/pcm/surround51.conf
index 3a7543f9fb8a..e67f007ef305 100644
--- a/src/conf/pcm/surround51.conf
+++ b/src/conf/pcm/surround51.conf
@@ -56,6 +56,6 @@ pcm.!surround51 {
}
hint {
description "5.1 Surround output to Front, Center, Rear and Subwoofer speakers"
- device $DEV
+ device_output $DEV
}
}
diff --git a/src/conf/pcm/surround71.conf b/src/conf/pcm/surround71.conf
index 076a97d73716..a26c3f36c437 100644
--- a/src/conf/pcm/surround71.conf
+++ b/src/conf/pcm/surround71.conf
@@ -58,6 +58,6 @@ pcm.!surround71 {
}
hint {
description "7.1 Surround output to Front, Center, Side, Rear and Woofer speakers"
- device $DEV
+ device_output $DEV
}
}
--
2.8.3

View File

@ -1,339 +0,0 @@
From c9a0d7d601e8ab069f8745968c03c8470b24d20d Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 17 May 2016 15:39:07 +0200
Subject: [PATCH 09/15] conf: Add thread-safe global tree reference
Most of open functions in alsa-lib have the call pattern:
snd_config_update();
return snd_xxx_open(x, snd_config, ...);
This means that the toplevel config gets updated, and passed to a
local open function. Although snd_config_update() itself has a
pthread mutex to be thread safe, the whole procedure above isn't
thread safe. Namely, the global snd_config tree may be deleted and
recreated at any time while the open function is being processed.
This may lead to a data corruption and crash of the program.
For avoiding the corruption, this patch introduces a refcount to
config tree object. A few new helper functions are introduced as
well:
- snd_config_update_ref() does update and take the refcount of the
toplevel tree. The obtained config tree has to be freed via
snd_config_unref() below.
- snd_config_ref() and snd_config_unref() manage the refcount of the
config object. The latter eventually deletes the object when all
references are gone.
Along with these additions, the caller of snd_config_update() and
snd_config global tree in alsa-lib are replaced with the new helpers.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/conf.h | 4 +++
src/conf.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++
src/control/control.c | 8 +++--
src/hwdep/hwdep.c | 8 +++--
src/pcm/pcm.c | 8 +++--
src/rawmidi/rawmidi.c | 8 +++--
src/seq/seq.c | 8 +++--
src/timer/timer.c | 8 +++--
src/timer/timer_query.c | 8 +++--
9 files changed, 125 insertions(+), 14 deletions(-)
diff --git a/include/conf.h b/include/conf.h
index 087c05dc6bcf..5d293d583fbb 100644
--- a/include/conf.h
+++ b/include/conf.h
@@ -94,6 +94,10 @@ int snd_config_update_r(snd_config_t **top, snd_config_update_t **update, const
int snd_config_update_free(snd_config_update_t *update);
int snd_config_update_free_global(void);
+int snd_config_update_ref(snd_config_t **top);
+void snd_config_ref(snd_config_t *top);
+void snd_config_unref(snd_config_t *top);
+
int snd_config_search(snd_config_t *config, const char *key,
snd_config_t **result);
int snd_config_searchv(snd_config_t *config,
diff --git a/src/conf.c b/src/conf.c
index f8b7a6686529..a516611427ac 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -434,6 +434,7 @@ static pthread_once_t snd_config_update_mutex_once = PTHREAD_ONCE_INIT;
struct _snd_config {
char *id;
snd_config_type_t type;
+ int refcount; /* default = 0 */
union {
long integer;
long long integer64;
@@ -1825,6 +1826,10 @@ int snd_config_remove(snd_config_t *config)
* If the node is a compound node, its descendants (the whole subtree)
* are deleted recursively.
*
+ * The function is supposed to be called only for locally copied config
+ * trees. For the global tree, take the reference via #snd_config_update_ref
+ * and free it via #snd_config_unref.
+ *
* \par Conforming to:
* LSB 3.2
*
@@ -1833,6 +1838,10 @@ int snd_config_remove(snd_config_t *config)
int snd_config_delete(snd_config_t *config)
{
assert(config);
+ if (config->refcount > 0) {
+ config->refcount--;
+ return 0;
+ }
switch (config->type) {
case SND_CONFIG_TYPE_COMPOUND:
{
@@ -3833,6 +3842,8 @@ int snd_config_update_r(snd_config_t **_top, snd_config_update_t **_update, cons
* \warning Whenever #snd_config is updated, all string pointers and
* configuration node handles previously obtained from it may become
* invalid.
+ * For safer operations, use #snd_config_update_ref and release the config
+ * via #snd_config_unref.
*
* \par Errors:
* Any errors encountered when parsing the input or returned by hooks or
@@ -3851,6 +3862,74 @@ int snd_config_update(void)
return err;
}
+/**
+ * \brief Updates #snd_config and takes its reference.
+ * \return 0 if #snd_config was up to date, 1 if #snd_config was
+ * updated, otherwise a negative error code.
+ *
+ * Unlike #snd_config_update, this function increases a reference counter
+ * so that the obtained tree won't be deleted until unreferenced by
+ * #snd_config_unref.
+ *
+ * This function is supposed to be thread-safe.
+ */
+int snd_config_update_ref(snd_config_t **top)
+{
+ int err;
+
+ if (top)
+ *top = NULL;
+ snd_config_lock();
+ err = snd_config_update_r(&snd_config, &snd_config_global_update, NULL);
+ if (err >= 0) {
+ if (snd_config) {
+ if (top) {
+ snd_config->refcount++;
+ *top = snd_config;
+ }
+ } else {
+ err = -ENODEV;
+ }
+ }
+ snd_config_unlock();
+ return err;
+}
+
+/**
+ * \brief Take the reference of the config tree.
+ *
+ * Increases a reference counter of the given config tree.
+ *
+ * This function is supposed to be thread-safe.
+ */
+void snd_config_ref(snd_config_t *cfg)
+{
+ snd_config_lock();
+ if (cfg)
+ cfg->refcount++;
+ snd_config_unlock();
+}
+
+/**
+ * \brief Unreference the config tree.
+ *
+ * Decreases a reference counter of the given config tree, and eventually
+ * deletes the tree if all references are gone. This is the counterpart of
+ * #snd_config_unref.
+ *
+ * Also, the config taken via #snd_config_update_ref must be unreferenced
+ * by this function, too.
+ *
+ * This function is supposed to be thread-safe.
+ */
+void snd_config_unref(snd_config_t *cfg)
+{
+ snd_config_lock();
+ if (cfg)
+ snd_config_delete(cfg);
+ snd_config_unlock();
+}
+
/**
* \brief Frees a private update structure.
* \param[in] update The private update structure to free.
diff --git a/src/control/control.c b/src/control/control.c
index 8a5d530f2674..ae7884313c63 100644
--- a/src/control/control.c
+++ b/src/control/control.c
@@ -968,12 +968,16 @@ static int snd_ctl_open_noupdate(snd_ctl_t **ctlp, snd_config_t *root, const cha
*/
int snd_ctl_open(snd_ctl_t **ctlp, const char *name, int mode)
{
+ snd_config_t *top;
int err;
+
assert(ctlp && name);
- err = snd_config_update();
+ err = snd_config_update_ref(&top);
if (err < 0)
return err;
- return snd_ctl_open_noupdate(ctlp, snd_config, name, mode);
+ err = snd_ctl_open_noupdate(ctlp, top, name, mode);
+ snd_config_unref(top);
+ return err;
}
/**
diff --git a/src/hwdep/hwdep.c b/src/hwdep/hwdep.c
index 5dc791c99189..bac634bae14a 100644
--- a/src/hwdep/hwdep.c
+++ b/src/hwdep/hwdep.c
@@ -168,12 +168,16 @@ static int snd_hwdep_open_noupdate(snd_hwdep_t **hwdep, snd_config_t *root, cons
*/
int snd_hwdep_open(snd_hwdep_t **hwdep, const char *name, int mode)
{
+ snd_config_t *top;
int err;
+
assert(hwdep && name);
- err = snd_config_update();
+ err = snd_config_update_ref(&top);
if (err < 0)
return err;
- return snd_hwdep_open_noupdate(hwdep, snd_config, name, mode);
+ err = snd_hwdep_open_noupdate(hwdep, top, name, mode);
+ snd_config_unref(top);
+ return err;
}
/**
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
index 203e7a52491b..0d0d093deb49 100644
--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -2288,12 +2288,16 @@ static int snd_pcm_open_noupdate(snd_pcm_t **pcmp, snd_config_t *root,
int snd_pcm_open(snd_pcm_t **pcmp, const char *name,
snd_pcm_stream_t stream, int mode)
{
+ snd_config_t *top;
int err;
+
assert(pcmp && name);
- err = snd_config_update();
+ err = snd_config_update_ref(&top);
if (err < 0)
return err;
- return snd_pcm_open_noupdate(pcmp, snd_config, name, stream, mode, 0);
+ err = snd_pcm_open_noupdate(pcmp, top, name, stream, mode, 0);
+ snd_config_unref(top);
+ return err;
}
/**
diff --git a/src/rawmidi/rawmidi.c b/src/rawmidi/rawmidi.c
index 0c89b8b984b9..4701b4375359 100644
--- a/src/rawmidi/rawmidi.c
+++ b/src/rawmidi/rawmidi.c
@@ -305,12 +305,16 @@ static int snd_rawmidi_open_noupdate(snd_rawmidi_t **inputp, snd_rawmidi_t **out
int snd_rawmidi_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
const char *name, int mode)
{
+ snd_config_t *top;
int err;
+
assert((inputp || outputp) && name);
- err = snd_config_update();
+ err = snd_config_update_ref(&top);
if (err < 0)
return err;
- return snd_rawmidi_open_noupdate(inputp, outputp, snd_config, name, mode);
+ err = snd_rawmidi_open_noupdate(inputp, outputp, top, name, mode);
+ snd_config_unref(top);
+ return err;
}
/**
diff --git a/src/seq/seq.c b/src/seq/seq.c
index 4405e68a7fe9..92798308a3b0 100644
--- a/src/seq/seq.c
+++ b/src/seq/seq.c
@@ -974,12 +974,16 @@ static int snd_seq_open_noupdate(snd_seq_t **seqp, snd_config_t *root,
int snd_seq_open(snd_seq_t **seqp, const char *name,
int streams, int mode)
{
+ snd_config_t *top;
int err;
+
assert(seqp && name);
- err = snd_config_update();
+ err = snd_config_update_ref(&top);
if (err < 0)
return err;
- return snd_seq_open_noupdate(seqp, snd_config, name, streams, mode, 0);
+ err = snd_seq_open_noupdate(seqp, top, name, streams, mode, 0);
+ snd_config_unref(top);
+ return err;
}
/**
diff --git a/src/timer/timer.c b/src/timer/timer.c
index a25e4f797ce4..b25347117cba 100644
--- a/src/timer/timer.c
+++ b/src/timer/timer.c
@@ -201,12 +201,16 @@ static int snd_timer_open_noupdate(snd_timer_t **timer, snd_config_t *root, cons
*/
int snd_timer_open(snd_timer_t **timer, const char *name, int mode)
{
+ snd_config_t *top;
int err;
+
assert(timer && name);
- err = snd_config_update();
+ err = snd_config_update_ref(&top);
if (err < 0)
return err;
- return snd_timer_open_noupdate(timer, snd_config, name, mode);
+ err = snd_timer_open_noupdate(timer, top, name, mode);
+ snd_config_unref(top);
+ return err;
}
/**
diff --git a/src/timer/timer_query.c b/src/timer/timer_query.c
index 93d2455d07fc..2072ceaea349 100644
--- a/src/timer/timer_query.c
+++ b/src/timer/timer_query.c
@@ -159,12 +159,16 @@ static int snd_timer_query_open_noupdate(snd_timer_query_t **timer, snd_config_t
*/
int snd_timer_query_open(snd_timer_query_t **timer, const char *name, int mode)
{
+ snd_config_t *top;
int err;
+
assert(timer && name);
- err = snd_config_update();
+ err = snd_config_update_ref(&top);
if (err < 0)
return err;
- return snd_timer_query_open_noupdate(timer, snd_config, name, mode);
+ err = snd_timer_query_open_noupdate(timer, top, name, mode);
+ snd_config_unref(top);
+ return err;
}
/**
--
2.8.3

View File

@ -1,70 +0,0 @@
From d942498bfbd315c4c4559ccd573685e09aa03383 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 18 May 2016 10:38:27 +0200
Subject: [PATCH 10/15] pcm: Remove resume support from dmix & co
PCM dmix and other plugins inherit the resume behavior from the slave
PCM. However, the resume on dmix can't work reliably even if the
slave PCM may do resume. The running state of each dmix stream is
individual and may be PREPARED or RUN_PENDING while the slave PCM is
already in RUNNING. And, when the slave PCM is resumed, the whole
samples that have been already mapped are also played back, even if
the corresponding dmix stream is still in SUSPENDED. Such
inconsistencies can't be avoided as long as we manage each stream
individually.
That said, dmix & co can't provide the proper resume support "by
design". For aligning with it, we should drop the whole resume code
and clear the PCM SND_PCM_INFO_RESUME flag.
Reported-by: Shengjiu Wang <shengjiu.wang@nxp.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_direct.c | 24 ++----------------------
1 file changed, 2 insertions(+), 22 deletions(-)
diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
index ac082f1a73b2..53c49929cb1f 100644
--- a/src/pcm/pcm_direct.c
+++ b/src/pcm/pcm_direct.c
@@ -837,27 +837,7 @@ int snd_pcm_direct_prepare(snd_pcm_t *pcm)
int snd_pcm_direct_resume(snd_pcm_t *pcm)
{
- snd_pcm_direct_t *dmix = pcm->private_data;
- 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? */
- snd_pcm_prepare(dmix->spcm);
- 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;
+ return -ENOSYS;
}
#define COPY_SLAVE(field) (dmix->shmptr->s.field = spcm->field)
@@ -865,7 +845,7 @@ int snd_pcm_direct_resume(snd_pcm_t *pcm)
/* copy the slave setting */
static void save_slave_setting(snd_pcm_direct_t *dmix, snd_pcm_t *spcm)
{
- spcm->info &= ~SND_PCM_INFO_PAUSE;
+ spcm->info &= ~(SND_PCM_INFO_PAUSE | SND_PCM_INFO_RESUME);
COPY_SLAVE(access);
COPY_SLAVE(format);
--
2.8.3

View File

@ -1,67 +0,0 @@
From 2fa36eb03c000560128f7abce701536546b4a618 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Sat, 28 May 2016 10:37:26 +0200
Subject: [PATCH 11/15] pcm: Fix secondary retry in dsnoop and dshare
The commit [fdba9e1bad8f: pcm: Fallback open as the first instance for
dmix & co] introduced a mechanism to retry the open of slave PCM for
the secondary streams, but this also introduced a regression in dsnoop
and dshare plugins: since the retry goto-tag was placed at a wrong
position, it retries to re-fetch the shm unnecessarily and eventually
leads to the fatal error.
The bug can be easily reproduced by starting arecord and killing it
via SIGKILL, then starting arecord again. The second arecord fails.
The fix is obviously to move the wrong retry goto-tags to the right
positions.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_dshare.c | 2 +-
src/pcm/pcm_dsnoop.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c
index adb3587a2869..05854dedf259 100644
--- a/src/pcm/pcm_dshare.c
+++ b/src/pcm/pcm_dshare.c
@@ -690,7 +690,6 @@ 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");
@@ -705,6 +704,7 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name,
dshare->max_periods = opts->max_periods;
dshare->sync_ptr = snd_pcm_dshare_sync_ptr;
+ retry:
if (first_instance) {
/* recursion is already checked in
snd_pcm_direct_get_slave_ipc_offset() */
diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c
index 8ff0ba57cb14..2d45171dda01 100644
--- a/src/pcm/pcm_dsnoop.c
+++ b/src/pcm/pcm_dsnoop.c
@@ -583,7 +583,6 @@ 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");
@@ -598,6 +597,7 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name,
dsnoop->max_periods = opts->max_periods;
dsnoop->sync_ptr = snd_pcm_dsnoop_sync_ptr;
+ retry:
if (first_instance) {
/* recursion is already checked in
snd_pcm_direct_get_slave_ipc_offset() */
--
2.8.3

View File

@ -1,72 +0,0 @@
From 6d1d620eadf32c6d963468ce56ff52cc3a2f32e2 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 25 May 2016 15:03:51 +0200
Subject: [PATCH 12/15] pcm: dmix: resume workaround for buggy driver
The previous commit removed the whole handling of resume in dmix, but
this seems causing another regression; some buggy drivers assume that
the device-resume needs to be triggered before transitioning to
PREPARED state. As an ugly workaround, in this patch, when the slave
PCM supports resume, snd_pcm_direct_resume() does resume of the slave
PCM but immediately drop the stream after that. In that way, the
device is brought to the sane active state, then the apps can prepare
and restart the stream properly.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_direct.c | 25 ++++++++++++++++++++++++-
1 file changed, 24 insertions(+), 1 deletion(-)
diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
index 53c49929cb1f..343fd3c6da3c 100644
--- a/src/pcm/pcm_direct.c
+++ b/src/pcm/pcm_direct.c
@@ -837,6 +837,27 @@ int snd_pcm_direct_prepare(snd_pcm_t *pcm)
int snd_pcm_direct_resume(snd_pcm_t *pcm)
{
+ snd_pcm_direct_t *dmix = pcm->private_data;
+ snd_pcm_t *spcm = dmix->spcm;
+
+ snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
+ /* some buggy drivers require the device resumed before prepared;
+ * when a device has RESUME flag and is in SUSPENDED state, resume
+ * here but immediately drop to bring it to a sane active state.
+ */
+ if ((spcm->info & SND_PCM_INFO_RESUME) &&
+ snd_pcm_state(spcm) == SND_PCM_STATE_SUSPENDED) {
+ snd_pcm_resume(spcm);
+ snd_pcm_drop(spcm);
+ snd_pcm_direct_timer_stop(dmix);
+ snd_pcm_direct_clear_timer_queue(dmix);
+ snd_pcm_areas_silence(snd_pcm_mmap_areas(spcm), 0,
+ spcm->channels, spcm->buffer_size,
+ spcm->format);
+ snd_pcm_prepare(spcm);
+ snd_pcm_start(spcm);
+ }
+ snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
return -ENOSYS;
}
@@ -845,7 +866,7 @@ int snd_pcm_direct_resume(snd_pcm_t *pcm)
/* copy the slave setting */
static void save_slave_setting(snd_pcm_direct_t *dmix, snd_pcm_t *spcm)
{
- spcm->info &= ~(SND_PCM_INFO_PAUSE | SND_PCM_INFO_RESUME);
+ spcm->info &= ~SND_PCM_INFO_PAUSE;
COPY_SLAVE(access);
COPY_SLAVE(format);
@@ -874,6 +895,8 @@ static void save_slave_setting(snd_pcm_direct_t *dmix, snd_pcm_t *spcm)
COPY_SLAVE(buffer_time);
COPY_SLAVE(sample_bits);
COPY_SLAVE(frame_bits);
+
+ dmix->shmptr->s.info &= ~SND_PCM_INFO_RESUME;
}
#undef COPY_SLAVE
--
2.8.3

View File

@ -1,27 +0,0 @@
From 8feb96ed9b457c2aa62ddea2c48651475b7c3411 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 31 May 2016 12:46:03 +0200
Subject: [PATCH 13/15] pcm: dmix: Prepare slave when it's in SETUP, too
SETUP is an unusual state, but it's still possible.
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 343fd3c6da3c..fbf9a592a4bc 100644
--- a/src/pcm/pcm_direct.c
+++ b/src/pcm/pcm_direct.c
@@ -819,6 +819,7 @@ int snd_pcm_direct_prepare(snd_pcm_t *pcm)
int err;
switch (snd_pcm_state(dmix->spcm)) {
+ case SND_PCM_STATE_SETUP:
case SND_PCM_STATE_XRUN:
case SND_PCM_STATE_SUSPENDED:
case SND_PCM_STATE_DISCONNECTED:
--
2.8.3

View File

@ -1,37 +0,0 @@
From 614ce73d3d6eba13946f863bec24981d355902e1 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 31 May 2016 12:48:40 +0200
Subject: [PATCH 14/15] pcm: dmix: Return error when slave is in OPEN or
DISCONNECTED
A slave PCM in OPEN or DISCONNECTED state can't be used properly at
all, so the best option is to return -EBADFD error.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_direct.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
index fbf9a592a4bc..21f98e7a1779 100644
--- a/src/pcm/pcm_direct.c
+++ b/src/pcm/pcm_direct.c
@@ -822,12 +822,14 @@ int snd_pcm_direct_prepare(snd_pcm_t *pcm)
case SND_PCM_STATE_SETUP:
case SND_PCM_STATE_XRUN:
case SND_PCM_STATE_SUSPENDED:
- case SND_PCM_STATE_DISCONNECTED:
err = snd_pcm_prepare(dmix->spcm);
if (err < 0)
return err;
snd_pcm_start(dmix->spcm);
break;
+ case SND_PCM_STATE_OPEN:
+ case SND_PCM_STATE_DISCONNECTED:
+ return -EBADFD;
}
snd_pcm_direct_check_interleave(dmix, pcm);
dmix->state = SND_PCM_STATE_PREPARED;
--
2.8.3

View File

@ -1,84 +0,0 @@
From d39e1879b9c72d51fe1ca4aeb5ba742e97b2175a Mon Sep 17 00:00:00 2001
From: Eliot Miranda <eliot.miranda@gmail.com>
Date: Wed, 1 Jun 2016 08:16:31 +0200
Subject: [PATCH 15/15] async: Handle previously installed signal handler
The issue is with the signal handler installed and deinstalled in
alsa-lib async handler. This code makes no attempt to remember any
previously installed signal handlers for SIGIO, if SIGIO is used.
Consequently it does not call any previous handlers from its own
handler once installed, and does not reinstall any previous handler
when deinstalling its handler. Consequently, use of also-lib within
applications that depend on SIGIO will break those applications,
rendering them inoperative once alsa-lib is running because their
signal handlers are no longer called.
This patch does remember and restore any previous handler, and chains
calls to the handler if it exists.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/async.c | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/src/async.c b/src/async.c
index 98aec78e00a8..0e133c3a34cd 100644
--- a/src/async.c
+++ b/src/async.c
@@ -28,6 +28,9 @@
#include "control/control_local.h"
#include <signal.h>
+static struct sigaction previous_action;
+#define MAX_SIG_FUNCTION_CODE 10 /* i.e. SIG_DFL SIG_IGN SIG_HOLD et al */
+
#ifdef SND_ASYNC_RT_SIGNAL
/** async signal number */
static int snd_async_signo;
@@ -54,6 +57,9 @@ static void snd_async_handler(int signo ATTRIBUTE_UNUSED, siginfo_t *siginfo, vo
int fd;
struct list_head *i;
//assert(siginfo->si_code == SI_SIGIO);
+ if (signo == SIGIO
+ && (unsigned long)(previous_action.sa_sigaction) > MAX_SIG_FUNCTION_CODE)
+ previous_action.sa_sigaction(signo, siginfo, context);
fd = siginfo->si_fd;
list_for_each(i, &snd_async_handlers) {
snd_async_handler_t *h = list_entry(i, snd_async_handler_t, glist);
@@ -114,7 +120,8 @@ int snd_async_add_handler(snd_async_handler_t **handler, int fd,
act.sa_flags = SA_RESTART | SA_SIGINFO;
act.sa_sigaction = snd_async_handler;
sigemptyset(&act.sa_mask);
- err = sigaction(snd_async_signo, &act, NULL);
+ assert(!previous_action.sa_sigaction);
+ err = sigaction(snd_async_signo, &act, &previous_action);
if (err < 0) {
SYSERR("sigaction");
return -errno;
@@ -131,18 +138,17 @@ int snd_async_add_handler(snd_async_handler_t **handler, int fd,
int snd_async_del_handler(snd_async_handler_t *handler)
{
int err = 0;
+ int was_empty = list_empty(&snd_async_handlers);
assert(handler);
list_del(&handler->glist);
- if (list_empty(&snd_async_handlers)) {
- struct sigaction act;
- memset(&act, 0, sizeof(act));
- act.sa_flags = 0;
- act.sa_handler = SIG_DFL;
- err = sigaction(snd_async_signo, &act, NULL);
+ if (!was_empty
+ && list_empty(&snd_async_handlers)) {
+ err = sigaction(snd_async_signo, &previous_action, NULL);
if (err < 0) {
SYSERR("sigaction");
return -errno;
}
+ memset(&previous_action, 0, sizeof(previous_action));
}
if (handler->type == SND_ASYNC_HANDLER_GENERIC)
goto _end;
--
2.8.3

View File

@ -1,12 +0,0 @@
---
doc/doxygen.cfg.in | 2 ++
1 file changed, 2 insertions(+)
--- a/doc/doxygen.cfg.in
+++ b/doc/doxygen.cfg.in
@@ -121,3 +121,5 @@ TYPEDEF_HIDES_STRUCT = YES # needed in d
#INPUT_FILTER = inputfilter
#FILTER_SOURCE_FILES = YES
+
+HTML_TIMESTAMP = NO

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8ac76c3144ed2ed49da7622ab65ac5415205913ccbedde877972383cbc234269
size 932105

3
alsa-lib-1.1.2.tar.bz2 Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d38dacd9892b06b8bff04923c380b38fb2e379ee5538935ff37e45b395d861d6
size 947423

View File

@ -1,3 +1,39 @@
-------------------------------------------------------------------
Wed Aug 3 11:22:16 CEST 2016 - tiwai@suse.de
- Update to alsa-lib v1.1.2:
* topology API updates
* support of stacked async handlers
* new UCM configs: rockchip-i2s, skylake-i2s, chtrt5645,
* add cset-tlv ucm support
* fix conversion of TLVs min_db and max_dB value in softvol
* fix appl pointer in the error path of PCM plugin
* PCM code cleanup
* fix suspend/resume of PCM dmix, dsnoop and dshare plugins
* fix doubly enumerated items via namehint
* make PCM codes thread-safe
* API documentation enhancements
* element-set ctl API
* Optimization by replacing alloca() usages
- Drop obsoleted patches:
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
0007-namehint-Don-t-enumerate-as-duplex-if-only-a-single-.patch
0008-pcm-Define-namehint-for-single-directional-PCM-types.patch
0009-conf-Add-thread-safe-global-tree-reference.patch
0010-pcm-Remove-resume-support-from-dmix-co.patch
0011-pcm-Fix-secondary-retry-in-dsnoop-and-dshare.patch
0012-pcm-dmix-resume-workaround-for-buggy-driver.patch
0013-pcm-dmix-Prepare-slave-when-it-s-in-SETUP-too.patch
0014-pcm-dmix-Return-error-when-slave-is-in-OPEN-or-DISCO.patch
0015-async-Handle-previously-installed-signal-handler.patch
alsa-docs-suppress-timestamp.patch
-------------------------------------------------------------------
Wed Jun 8 10:30:29 CEST 2016 - tiwai@suse.de

View File

@ -16,16 +16,15 @@
#
%define package_version 1.1.1
%define package_version 1.1.2
%if 0%{?suse_version} > 1200
%define _udevdir %(pkg-config --variable=udevdir udev)
%else
%define _udevdir /lib/udev
%endif
Name: alsa
Version: 1.1.1
Version: 1.1.2
Release: 0
#
Summary: Advanced Linux Sound Architecture
License: LGPL-2.1+
Group: System/Libraries
@ -49,25 +48,8 @@ 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
Patch7: 0007-namehint-Don-t-enumerate-as-duplex-if-only-a-single-.patch
Patch8: 0008-pcm-Define-namehint-for-single-directional-PCM-types.patch
Patch9: 0009-conf-Add-thread-safe-global-tree-reference.patch
Patch10: 0010-pcm-Remove-resume-support-from-dmix-co.patch
Patch11: 0011-pcm-Fix-secondary-retry-in-dsnoop-and-dshare.patch
Patch12: 0012-pcm-dmix-resume-workaround-for-buggy-driver.patch
Patch13: 0013-pcm-dmix-Prepare-slave-when-it-s-in-SETUP-too.patch
Patch14: 0014-pcm-dmix-Return-error-when-slave-is-in-OPEN-or-DISCO.patch
Patch15: 0015-async-Handle-previously-installed-signal-handler.patch
# rest suse patches
Patch99: alsa-lib-doxygen-avoid-crash-for-11.3.diff
# suppress timestamp in documents
Patch100: alsa-docs-suppress-timestamp.patch
BuildRequires: doxygen
BuildRequires: libtool
BuildRequires: pkg-config
@ -134,25 +116,9 @@ Architecture.
%prep
%setup -q -n alsa-lib-%{package_version}
# %patch -p1
%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%patch5 -p1
%patch6 -p1
%patch7 -p1
%patch8 -p1
%patch9 -p1
%patch10 -p1
%patch11 -p1
%patch12 -p1
%patch13 -p1
%patch14 -p1
%patch15 -p1
%if 0%{?suse_version} == 1130
%patch99 -p1
%endif
%patch100 -p1
# hack to fix build on older distros
%if 0%{?suse_version} < 1100
%ifarch %{ix86}