diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h index 175ab3237b58..ae6c3b8ed2f5 100644 --- a/include/sound/compress_driver.h +++ b/include/sound/compress_driver.h @@ -48,8 +48,6 @@ struct snd_compr_ops; * the ring buffer * @total_bytes_transferred: cumulative bytes transferred by offload DSP * @sleep: poll sleep - * @wait: drain wait queue - * @drain_wake: condition for drain wake */ struct snd_compr_runtime { snd_pcm_state_t state; @@ -61,8 +59,6 @@ struct snd_compr_runtime { u64 total_bytes_available; u64 total_bytes_transferred; wait_queue_head_t sleep; - wait_queue_head_t wait; - unsigned int drain_wake; void *private_data; }; @@ -177,10 +173,11 @@ static inline void snd_compr_fragment_elapsed(struct snd_compr_stream *stream) static inline void snd_compr_drain_notify(struct snd_compr_stream *stream) { - snd_BUG_ON(!stream); + if (snd_BUG_ON(!stream)) + return; - stream->runtime->drain_wake = 1; - wake_up(&stream->runtime->wait); + stream->runtime->state = SNDRV_PCM_STATE_SETUP; + wake_up(&stream->runtime->sleep); } #endif diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 3eb47d0006a7..d9af6387f37c 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -123,7 +123,6 @@ static int snd_compr_open(struct inode *inode, struct file *f) } runtime->state = SNDRV_PCM_STATE_OPEN; init_waitqueue_head(&runtime->sleep); - init_waitqueue_head(&runtime->wait); data->stream.runtime = runtime; f->private_data = (void *)data; mutex_lock(&compr->lock); @@ -681,8 +680,6 @@ static int snd_compr_stop(struct snd_compr_stream *stream) return -EPERM; retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP); if (!retval) { - stream->runtime->state = SNDRV_PCM_STATE_SETUP; - wake_up(&stream->runtime->sleep); snd_compr_drain_notify(stream); stream->runtime->total_bytes_available = 0; stream->runtime->total_bytes_transferred = 0; @@ -692,6 +689,8 @@ static int snd_compr_stop(struct snd_compr_stream *stream) static int snd_compress_wait_for_drain(struct snd_compr_stream *stream) { + int ret; + /* * We are called with lock held. So drop the lock while we wait for * drain complete notfication from the driver @@ -703,12 +702,24 @@ static int snd_compress_wait_for_drain(struct snd_compr_stream *stream) stream->runtime->state = SNDRV_PCM_STATE_DRAINING; mutex_unlock(&stream->device->lock); - wait_event(stream->runtime->wait, stream->runtime->drain_wake); + /* we wait for drain to complete here, drain can return when + * interruption occurred, wait returned error or success. + * For the first two cases we don't do anything different here and + * return after waking up + */ + + ret = wait_event_interruptible(stream->runtime->sleep, + (stream->runtime->state != SNDRV_PCM_STATE_DRAINING)); + if (ret == -ERESTARTSYS) + pr_debug("wait aborted by a signal"); + else if (ret) + pr_debug("wait for drain failed with %d\n", ret); + wake_up(&stream->runtime->sleep); mutex_lock(&stream->device->lock); - return 0; + return ret; } static int snd_compr_drain(struct snd_compr_stream *stream) @@ -719,17 +730,14 @@ static int snd_compr_drain(struct snd_compr_stream *stream) stream->runtime->state == SNDRV_PCM_STATE_SETUP) return -EPERM; - stream->runtime->drain_wake = 0; retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN); if (retval) { - pr_err("SND_COMPR_TRIGGER_DRAIN failed %d\n", retval); + pr_debug("SND_COMPR_TRIGGER_DRAIN failed %d\n", retval); wake_up(&stream->runtime->sleep); return retval; } - retval = snd_compress_wait_for_drain(stream); - stream->runtime->state = SNDRV_PCM_STATE_SETUP; - return retval; + return snd_compress_wait_for_drain(stream); } static int snd_compr_next_track(struct snd_compr_stream *stream) @@ -764,10 +772,9 @@ static int snd_compr_partial_drain(struct snd_compr_stream *stream) if (stream->next_track == false) return -EPERM; - stream->runtime->drain_wake = 0; retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_PARTIAL_DRAIN); if (retval) { - pr_err("Partial drain returned failure\n"); + pr_debug("Partial drain returned failure\n"); wake_up(&stream->runtime->sleep); return retval; }