Skip to content

Commit f2b3614

Browse files
committed
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: Raymond Yau <[email protected]> Signed-off-by: Takashi Iwai <[email protected]>
1 parent a331b0c commit f2b3614

File tree

2 files changed

+24
-6
lines changed

2 files changed

+24
-6
lines changed

sound/core/pcm_lib.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1756,18 +1756,27 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
17561756
wait_queue_t wait;
17571757
int err = 0;
17581758
snd_pcm_uframes_t avail = 0;
1759-
long tout;
1760-
1759+
long wait_time, tout;
1760+
1761+
if (runtime->no_period_wakeup)
1762+
wait_time = MAX_SCHEDULE_TIMEOUT;
1763+
else {
1764+
wait_time = 10;
1765+
if (runtime->rate) {
1766+
long t = runtime->period_size * 2 / runtime->rate;
1767+
wait_time = max(t, wait_time);
1768+
}
1769+
wait_time = msecs_to_jiffies(wait_time * 1000);
1770+
}
17611771
init_waitqueue_entry(&wait, current);
17621772
add_wait_queue(&runtime->tsleep, &wait);
17631773
for (;;) {
17641774
if (signal_pending(current)) {
17651775
err = -ERESTARTSYS;
17661776
break;
17671777
}
1768-
set_current_state(TASK_INTERRUPTIBLE);
17691778
snd_pcm_stream_unlock_irq(substream);
1770-
tout = schedule_timeout(msecs_to_jiffies(10000));
1779+
tout = schedule_timeout_interruptible(wait_time);
17711780
snd_pcm_stream_lock_irq(substream);
17721781
switch (runtime->status->state) {
17731782
case SNDRV_PCM_STATE_SUSPENDED:

sound/core/pcm_native.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1481,11 +1481,20 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
14811481
break; /* all drained */
14821482
init_waitqueue_entry(&wait, current);
14831483
add_wait_queue(&to_check->sleep, &wait);
1484-
set_current_state(TASK_INTERRUPTIBLE);
14851484
snd_pcm_stream_unlock_irq(substream);
14861485
up_read(&snd_pcm_link_rwsem);
14871486
snd_power_unlock(card);
1488-
tout = schedule_timeout(10 * HZ);
1487+
if (runtime->no_period_wakeup)
1488+
tout = MAX_SCHEDULE_TIMEOUT;
1489+
else {
1490+
tout = 10;
1491+
if (runtime->rate) {
1492+
long t = runtime->period_size * 2 / runtime->rate;
1493+
tout = max(t, tout);
1494+
}
1495+
tout = msecs_to_jiffies(tout * 1000);
1496+
}
1497+
tout = schedule_timeout_interruptible(tout);
14891498
snd_power_lock(card);
14901499
down_read(&snd_pcm_link_rwsem);
14911500
snd_pcm_stream_lock_irq(substream);

0 commit comments

Comments
 (0)