Commit f2b3614c authored by Takashi Iwai's avatar Takashi Iwai

ALSA: PCM - Don't check DMA time-out too shortly

When the PCM period size is set larger than 10 seconds, currently the
PCM core may abort the operation with DMA-error due to the fixed timeout
for 10 seconds.  A similar problem is seen in the drain operation that
has a fixed timeout of 10 seconds, too.

This patch fixes the timeout length depending on the period size and
rate, also including the consideration of no_period_wakeup flag.
Reported-by: default avatarRaymond Yau <superquad.vortex2@gmail.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent a331b0c3
...@@ -1756,8 +1756,18 @@ static int wait_for_avail(struct snd_pcm_substream *substream, ...@@ -1756,8 +1756,18 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
wait_queue_t wait; wait_queue_t wait;
int err = 0; int err = 0;
snd_pcm_uframes_t avail = 0; snd_pcm_uframes_t avail = 0;
long tout; long wait_time, tout;
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);
}
wait_time = msecs_to_jiffies(wait_time * 1000);
}
init_waitqueue_entry(&wait, current); init_waitqueue_entry(&wait, current);
add_wait_queue(&runtime->tsleep, &wait); add_wait_queue(&runtime->tsleep, &wait);
for (;;) { for (;;) {
...@@ -1765,9 +1775,8 @@ static int wait_for_avail(struct snd_pcm_substream *substream, ...@@ -1765,9 +1775,8 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
err = -ERESTARTSYS; err = -ERESTARTSYS;
break; break;
} }
set_current_state(TASK_INTERRUPTIBLE);
snd_pcm_stream_unlock_irq(substream); snd_pcm_stream_unlock_irq(substream);
tout = schedule_timeout(msecs_to_jiffies(10000)); tout = schedule_timeout_interruptible(wait_time);
snd_pcm_stream_lock_irq(substream); snd_pcm_stream_lock_irq(substream);
switch (runtime->status->state) { switch (runtime->status->state) {
case SNDRV_PCM_STATE_SUSPENDED: case SNDRV_PCM_STATE_SUSPENDED:
......
...@@ -1481,11 +1481,20 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, ...@@ -1481,11 +1481,20 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
break; /* all drained */ break; /* all drained */
init_waitqueue_entry(&wait, current); init_waitqueue_entry(&wait, current);
add_wait_queue(&to_check->sleep, &wait); add_wait_queue(&to_check->sleep, &wait);
set_current_state(TASK_INTERRUPTIBLE);
snd_pcm_stream_unlock_irq(substream); snd_pcm_stream_unlock_irq(substream);
up_read(&snd_pcm_link_rwsem); up_read(&snd_pcm_link_rwsem);
snd_power_unlock(card); snd_power_unlock(card);
tout = schedule_timeout(10 * HZ); if (runtime->no_period_wakeup)
tout = MAX_SCHEDULE_TIMEOUT;
else {
tout = 10;
if (runtime->rate) {
long t = runtime->period_size * 2 / runtime->rate;
tout = max(t, tout);
}
tout = msecs_to_jiffies(tout * 1000);
}
tout = schedule_timeout_interruptible(tout);
snd_power_lock(card); snd_power_lock(card);
down_read(&snd_pcm_link_rwsem); down_read(&snd_pcm_link_rwsem);
snd_pcm_stream_lock_irq(substream); snd_pcm_stream_lock_irq(substream);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment