diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-08-20 16:40:16 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-08-20 16:40:16 +0200 |
commit | 4cdc115fd38b54642e8536a5c2389483bcb9b2e9 (patch) | |
tree | e68cfe5e88d155d1a6820b563517dac27b8e6dd6 /sound/core/pcm_lib.c | |
parent | 64f1607ffbbc772685733ea63e6f7f4183df1b16 (diff) | |
download | linux-4cdc115fd38b54642e8536a5c2389483bcb9b2e9.tar.bz2 |
ALSA: pcm - Fix drain behavior in non-blocking mode
The current PCM core has the following problems regarding PCM draining
in non-blocking mode:
- the current f_flags isn't checked in snd_pcm_drain(), thus changing
the mode dynamically via snd_pcm_nonblock() after open doesn't work.
- calling drain in non-blocking mode just return -EAGAIN error, but
doesn't provide any way to sync with draining.
This patch fixes these issues.
- check file->f_flags in snd_pcm_drain() properly
- when O_NONBLOCK is set, PCM core sets the stream(s) to DRAIN state
but quits ioctl immediately without waiting the whole drain; the
caller can sync the drain manually via poll()
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core/pcm_lib.c')
-rw-r--r-- | sound/core/pcm_lib.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 72cfd47af6b8..e3e78c7f2745 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -197,12 +197,16 @@ static int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream, avail = snd_pcm_capture_avail(runtime); if (avail > runtime->avail_max) runtime->avail_max = avail; - if (avail >= runtime->stop_threshold) { - if (substream->runtime->status->state == SNDRV_PCM_STATE_DRAINING) + if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { + if (avail >= runtime->buffer_size) { snd_pcm_drain_done(substream); - else + return -EPIPE; + } + } else { + if (avail >= runtime->stop_threshold) { xrun(substream); - return -EPIPE; + return -EPIPE; + } } if (avail >= runtime->control->avail_min) wake_up(&runtime->sleep); |