Loading include/sound/asound.h +1 −1 Original line number Diff line number Diff line Loading @@ -138,7 +138,7 @@ struct snd_hwdep_dsp_image { * * *****************************************************************************/ #define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 9) #define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 10) typedef unsigned long snd_pcm_uframes_t; typedef signed long snd_pcm_sframes_t; Loading sound/core/pcm_lib.c +8 −4 Original line number Diff line number Diff line Loading @@ -197,13 +197,17 @@ 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; } } if (avail >= runtime->control->avail_min) wake_up(&runtime->sleep); return 0; Loading sound/core/pcm_native.c +29 −23 Original line number Diff line number Diff line Loading @@ -1343,8 +1343,6 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream, static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state) { if (substream->f_flags & O_NONBLOCK) return -EAGAIN; substream->runtime->trigger_master = substream; return 0; } Loading Loading @@ -1392,7 +1390,6 @@ static struct action_ops snd_pcm_action_drain_init = { struct drain_rec { struct snd_pcm_substream *substream; wait_queue_t wait; snd_pcm_uframes_t stop_threshold; }; static int snd_pcm_drop(struct snd_pcm_substream *substream); Loading @@ -1404,13 +1401,15 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream); * After this call, all streams are supposed to be either SETUP or DRAINING * (capture only) state. */ static int snd_pcm_drain(struct snd_pcm_substream *substream) static int snd_pcm_drain(struct snd_pcm_substream *substream, struct file *file) { struct snd_card *card; struct snd_pcm_runtime *runtime; struct snd_pcm_substream *s; int result = 0; int i, num_drecs; int nonblock = 0; struct drain_rec *drec, drec_tmp, *d; card = substream->pcm->card; Loading @@ -1428,6 +1427,15 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream) } } if (file) { if (file->f_flags & O_NONBLOCK) nonblock = 1; } else if (substream->f_flags & O_NONBLOCK) nonblock = 1; if (nonblock) goto lock; /* no need to allocate waitqueues */ /* allocate temporary record for drain sync */ down_read(&snd_pcm_link_rwsem); if (snd_pcm_stream_linked(substream)) { Loading @@ -1449,16 +1457,11 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream) d->substream = s; init_waitqueue_entry(&d->wait, current); add_wait_queue(&runtime->sleep, &d->wait); /* stop_threshold fixup to avoid endless loop when * stop_threshold > buffer_size */ d->stop_threshold = runtime->stop_threshold; if (runtime->stop_threshold > runtime->buffer_size) runtime->stop_threshold = runtime->buffer_size; } } up_read(&snd_pcm_link_rwsem); lock: snd_pcm_stream_lock_irq(substream); /* resume pause */ if (substream->runtime->status->state == SNDRV_PCM_STATE_PAUSED) Loading @@ -1466,9 +1469,12 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream) /* pre-start/stop - all running streams are changed to DRAINING state */ result = snd_pcm_action(&snd_pcm_action_drain_init, substream, 0); if (result < 0) { snd_pcm_stream_unlock_irq(substream); goto _error; if (result < 0) goto unlock; /* in non-blocking, we don't wait in ioctl but let caller poll */ if (nonblock) { result = -EAGAIN; goto unlock; } for (;;) { Loading Loading @@ -1504,18 +1510,18 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream) } } unlock: snd_pcm_stream_unlock_irq(substream); _error: if (!nonblock) { for (i = 0; i < num_drecs; i++) { d = &drec[i]; runtime = d->substream->runtime; remove_wait_queue(&runtime->sleep, &d->wait); runtime->stop_threshold = d->stop_threshold; } if (drec != &drec_tmp) kfree(drec); } snd_power_unlock(card); return result; Loading Loading @@ -2544,7 +2550,7 @@ static int snd_pcm_common_ioctl1(struct file *file, return snd_pcm_hw_params_old_user(substream, arg); #endif case SNDRV_PCM_IOCTL_DRAIN: return snd_pcm_drain(substream); return snd_pcm_drain(substream, file); case SNDRV_PCM_IOCTL_DROP: return snd_pcm_drop(substream); case SNDRV_PCM_IOCTL_PAUSE: Loading Loading
include/sound/asound.h +1 −1 Original line number Diff line number Diff line Loading @@ -138,7 +138,7 @@ struct snd_hwdep_dsp_image { * * *****************************************************************************/ #define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 9) #define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 10) typedef unsigned long snd_pcm_uframes_t; typedef signed long snd_pcm_sframes_t; Loading
sound/core/pcm_lib.c +8 −4 Original line number Diff line number Diff line Loading @@ -197,13 +197,17 @@ 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; } } if (avail >= runtime->control->avail_min) wake_up(&runtime->sleep); return 0; Loading
sound/core/pcm_native.c +29 −23 Original line number Diff line number Diff line Loading @@ -1343,8 +1343,6 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream, static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state) { if (substream->f_flags & O_NONBLOCK) return -EAGAIN; substream->runtime->trigger_master = substream; return 0; } Loading Loading @@ -1392,7 +1390,6 @@ static struct action_ops snd_pcm_action_drain_init = { struct drain_rec { struct snd_pcm_substream *substream; wait_queue_t wait; snd_pcm_uframes_t stop_threshold; }; static int snd_pcm_drop(struct snd_pcm_substream *substream); Loading @@ -1404,13 +1401,15 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream); * After this call, all streams are supposed to be either SETUP or DRAINING * (capture only) state. */ static int snd_pcm_drain(struct snd_pcm_substream *substream) static int snd_pcm_drain(struct snd_pcm_substream *substream, struct file *file) { struct snd_card *card; struct snd_pcm_runtime *runtime; struct snd_pcm_substream *s; int result = 0; int i, num_drecs; int nonblock = 0; struct drain_rec *drec, drec_tmp, *d; card = substream->pcm->card; Loading @@ -1428,6 +1427,15 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream) } } if (file) { if (file->f_flags & O_NONBLOCK) nonblock = 1; } else if (substream->f_flags & O_NONBLOCK) nonblock = 1; if (nonblock) goto lock; /* no need to allocate waitqueues */ /* allocate temporary record for drain sync */ down_read(&snd_pcm_link_rwsem); if (snd_pcm_stream_linked(substream)) { Loading @@ -1449,16 +1457,11 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream) d->substream = s; init_waitqueue_entry(&d->wait, current); add_wait_queue(&runtime->sleep, &d->wait); /* stop_threshold fixup to avoid endless loop when * stop_threshold > buffer_size */ d->stop_threshold = runtime->stop_threshold; if (runtime->stop_threshold > runtime->buffer_size) runtime->stop_threshold = runtime->buffer_size; } } up_read(&snd_pcm_link_rwsem); lock: snd_pcm_stream_lock_irq(substream); /* resume pause */ if (substream->runtime->status->state == SNDRV_PCM_STATE_PAUSED) Loading @@ -1466,9 +1469,12 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream) /* pre-start/stop - all running streams are changed to DRAINING state */ result = snd_pcm_action(&snd_pcm_action_drain_init, substream, 0); if (result < 0) { snd_pcm_stream_unlock_irq(substream); goto _error; if (result < 0) goto unlock; /* in non-blocking, we don't wait in ioctl but let caller poll */ if (nonblock) { result = -EAGAIN; goto unlock; } for (;;) { Loading Loading @@ -1504,18 +1510,18 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream) } } unlock: snd_pcm_stream_unlock_irq(substream); _error: if (!nonblock) { for (i = 0; i < num_drecs; i++) { d = &drec[i]; runtime = d->substream->runtime; remove_wait_queue(&runtime->sleep, &d->wait); runtime->stop_threshold = d->stop_threshold; } if (drec != &drec_tmp) kfree(drec); } snd_power_unlock(card); return result; Loading Loading @@ -2544,7 +2550,7 @@ static int snd_pcm_common_ioctl1(struct file *file, return snd_pcm_hw_params_old_user(substream, arg); #endif case SNDRV_PCM_IOCTL_DRAIN: return snd_pcm_drain(substream); return snd_pcm_drain(substream, file); case SNDRV_PCM_IOCTL_DROP: return snd_pcm_drop(substream); case SNDRV_PCM_IOCTL_PAUSE: Loading