summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLiam Girdwood <liam.r.girdwood@linux.intel.com>2018-07-06 15:50:36 +0300
committerTakashi Iwai <tiwai@suse.de>2018-07-06 16:00:25 +0300
commitd64c5cf8e89d124355924c513a42b16f0d7d3a03 (patch)
tree2d75c2a4644e0492a1434e0b999ab1d5a5a31de0
parente647f5a5c5d165c87750e8c0dcbe341b5a378ffd (diff)
downloadlinux-d64c5cf8e89d124355924c513a42b16f0d7d3a03.tar.xz
ALSA: pcm: Allow drivers to set R/W wait time.
Currently ALSA core blocks userspace for about 10 seconds for PCM R/W IO. This needs to be configurable for modern hardware like DSPs where no pointer update in milliseconds can indicate terminal DSP errors. Add a substream variable to set the wait time in ms. This allows userspace and drivers to recover more quickly from terminal DSP errors. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--include/sound/pcm.h1
-rw-r--r--sound/core/pcm_lib.c17
2 files changed, 13 insertions, 5 deletions
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index e054c583d3b3..fcdf358a25f0 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -462,6 +462,7 @@ struct snd_pcm_substream {
/* -- timer section -- */
struct snd_timer *timer; /* timer */
unsigned timer_running: 1; /* time is running */
+ long wait_time; /* time in ms for R/W to wait for avail */
/* -- next substream -- */
struct snd_pcm_substream *next;
/* -- linked substreams -- */
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index c1d2e8e1fc6b..5736860f325b 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -1833,12 +1833,19 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
if (runtime->no_period_wakeup)
wait_time = MAX_SCHEDULE_TIMEOUT;
else {
- wait_time = 10;
- if (runtime->rate) {
- long t = runtime->period_size * 2 / runtime->rate;
- wait_time = max(t, wait_time);
+ /* use wait time from substream if available */
+ if (substream->wait_time) {
+ wait_time = substream->wait_time;
+ } else {
+ wait_time = 10;
+
+ if (runtime->rate) {
+ long t = runtime->period_size * 2 /
+ runtime->rate;
+ wait_time = max(t, wait_time);
+ }
+ wait_time = msecs_to_jiffies(wait_time * 1000);
}
- wait_time = msecs_to_jiffies(wait_time * 1000);
}
for (;;) {