alsa-devel.alsa-project.org archive mirror
 help / color / mirror / Atom feed
From: Vinod Koul <vinod.koul@intel.com>
To: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
Cc: lgirdwood@gmail.com, alsa-devel@alsa-project.org,
	broonie@kernel.org, tiwai@suse.com,
	patches@opensource.wolfsonmicro.com
Subject: Re: [PATCH 2/4] ALSA: compress: Handle errors during avail requests
Date: Fri, 11 Mar 2016 13:24:00 +0530	[thread overview]
Message-ID: <20160311075400.GW11154@localhost> (raw)
In-Reply-To: <1457606694-10985-2-git-send-email-ckeepax@opensource.wolfsonmicro.com>

On Thu, Mar 10, 2016 at 10:44:52AM +0000, Charles Keepax wrote:
> No errors are currently returned whilst checking the amount of available
> data. If user-space does an avail request which encounters an error it

How do you detect an error? Is DSP sending you error or just fails to
respond? ALso note that in compress formats, DSP may still be decoding the
data and rendering while we thing pointers are not moving

Also while at it, I am thinking exporting snd_compr_stop() might be a better
idea, if you can reliably detect error then stop the stream...

> will generally return zero, causing user-space to poll and if each
> subsequence avail request also returns zero it will wait indefinitely for
> data that is never coming. This patch updates the code so that errors
> during avail requests will be correctly propagated to user-space.
> 
> Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
> ---
>  sound/core/compress_offload.c | 64 +++++++++++++++++++++++++++++++------------
>  1 file changed, 47 insertions(+), 17 deletions(-)
> 
> diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
> index 7fac3ca..c9c0849 100644
> --- a/sound/core/compress_offload.c
> +++ b/sound/core/compress_offload.c
> @@ -170,9 +170,15 @@ static int snd_compr_free(struct inode *inode, struct file *f)
>  static int snd_compr_update_tstamp(struct snd_compr_stream *stream,
>  		struct snd_compr_tstamp *tstamp)
>  {
> +	int ret;
> +
>  	if (!stream->ops->pointer)
>  		return -ENOTSUPP;
> -	stream->ops->pointer(stream, tstamp);
> +
> +	ret = stream->ops->pointer(stream, tstamp);
> +	if (ret < 0)
> +		return ret;
> +
>  	pr_debug("dsp consumed till %d total %d bytes\n",
>  		tstamp->byte_offset, tstamp->copied_total);
>  	if (stream->direction == SND_COMPRESS_PLAYBACK)
> @@ -182,18 +188,24 @@ static int snd_compr_update_tstamp(struct snd_compr_stream *stream,
>  	return 0;
>  }
>  
> -static size_t snd_compr_calc_avail(struct snd_compr_stream *stream,
> +static int snd_compr_calc_avail(struct snd_compr_stream *stream,
>  		struct snd_compr_avail *avail)
>  {
> +	int ret;
> +
>  	memset(avail, 0, sizeof(*avail));
> -	snd_compr_update_tstamp(stream, &avail->tstamp);
> +	ret = snd_compr_update_tstamp(stream, &avail->tstamp);
> +	if (ret < 0)
> +		return ret;
> +
>  	/* Still need to return avail even if tstamp can't be filled in */
>  
>  	if (stream->runtime->total_bytes_available == 0 &&
>  			stream->runtime->state == SNDRV_PCM_STATE_SETUP &&
>  			stream->direction == SND_COMPRESS_PLAYBACK) {
>  		pr_debug("detected init and someone forgot to do a write\n");
> -		return stream->runtime->buffer_size;
> +		avail->avail = stream->runtime->buffer_size;
> +		return 0;
>  	}
>  	pr_debug("app wrote %lld, DSP consumed %lld\n",
>  			stream->runtime->total_bytes_available,
> @@ -202,9 +214,11 @@ static size_t snd_compr_calc_avail(struct snd_compr_stream *stream,
>  				stream->runtime->total_bytes_transferred) {
>  		if (stream->direction == SND_COMPRESS_PLAYBACK) {
>  			pr_debug("both pointers are same, returning full avail\n");
> -			return stream->runtime->buffer_size;
> +			avail->avail = stream->runtime->buffer_size;
> +			return 0;
>  		} else {
>  			pr_debug("both pointers are same, returning no avail\n");
> +			avail->avail = 0;
>  			return 0;
>  		}
>  	}
> @@ -215,24 +229,30 @@ static size_t snd_compr_calc_avail(struct snd_compr_stream *stream,
>  		avail->avail = stream->runtime->buffer_size - avail->avail;
>  
>  	pr_debug("ret avail as %lld\n", avail->avail);
> -	return avail->avail;
> +	return 0;
>  }
>  
> -static inline size_t snd_compr_get_avail(struct snd_compr_stream *stream)
> +static inline int snd_compr_get_avail(struct snd_compr_stream *stream,
> +				      size_t *avail)
>  {
> -	struct snd_compr_avail avail;
> +	struct snd_compr_avail full_avail;
> +	int ret;
> +
> +	ret = snd_compr_calc_avail(stream, &full_avail);
> +	*avail = full_avail.avail;
>  
> -	return snd_compr_calc_avail(stream, &avail);
> +	return ret;
>  }
>  
>  static int
>  snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg)
>  {
>  	struct snd_compr_avail ioctl_avail;
> -	size_t avail;
> +	int ret;
>  
> -	avail = snd_compr_calc_avail(stream, &ioctl_avail);
> -	ioctl_avail.avail = avail;
> +	ret = snd_compr_calc_avail(stream, &ioctl_avail);
> +	if (ret < 0)
> +		return ret;
>  
>  	if (copy_to_user((__u64 __user *)arg,
>  				&ioctl_avail, sizeof(ioctl_avail)))
> @@ -287,11 +307,14 @@ static ssize_t snd_compr_write(struct file *f, const char __user *buf,
>  	/* write is allowed when stream is running or has been steup */
>  	if (stream->runtime->state != SNDRV_PCM_STATE_SETUP &&
>  			stream->runtime->state != SNDRV_PCM_STATE_RUNNING) {
> -		mutex_unlock(&stream->device->lock);
> -		return -EBADFD;
> +		retval = -EBADFD;
> +		goto out;
>  	}
>  
> -	avail = snd_compr_get_avail(stream);
> +	retval = snd_compr_get_avail(stream, &avail);
> +	if (retval < 0)
> +		goto out;
> +
>  	pr_debug("avail returned %ld\n", (unsigned long)avail);
>  	/* calculate how much we can write to buffer */
>  	if (avail > count)
> @@ -313,6 +336,7 @@ static ssize_t snd_compr_write(struct file *f, const char __user *buf,
>  		pr_debug("stream prepared, Houston we are good to go\n");
>  	}
>  
> +out:
>  	mutex_unlock(&stream->device->lock);
>  	return retval;
>  }
> @@ -346,7 +370,10 @@ static ssize_t snd_compr_read(struct file *f, char __user *buf,
>  		goto out;
>  	}
>  
> -	avail = snd_compr_get_avail(stream);
> +	retval = snd_compr_get_avail(stream, &avail);
> +	if (retval < 0)
> +		goto out;
> +
>  	pr_debug("avail returned %ld\n", (unsigned long)avail);
>  	/* calculate how much we can read from buffer */
>  	if (avail > count)
> @@ -399,7 +426,10 @@ static unsigned int snd_compr_poll(struct file *f, poll_table *wait)
>  	}
>  	poll_wait(f, &stream->runtime->sleep, wait);
>  
> -	avail = snd_compr_get_avail(stream);
> +	retval = snd_compr_get_avail(stream, &avail);
> +	if (retval < 0)
> +		goto out;
> +
>  	pr_debug("avail is %ld\n", (unsigned long)avail);
>  	/* check if we have at least one fragment to fill */
>  	switch (stream->runtime->state) {
> -- 
> 2.1.4
> 
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel@alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

-- 
~Vinod

  reply	other threads:[~2016-03-11  7:49 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-10 10:44 [PATCH 1/4] ASoC: compress: Pass error out of soc_compr_pointer Charles Keepax
2016-03-10 10:44 ` [PATCH 2/4] ALSA: compress: Handle errors during avail requests Charles Keepax
2016-03-11  7:54   ` Vinod Koul [this message]
2016-03-10 10:44 ` [PATCH 3/4] ASoC: wm_adsp: Factor out checking of stream errors from the DSP Charles Keepax
2016-03-10 10:44 ` [PATCH 4/4] ASoC: wm_adsp: Improve DSP error handling Charles Keepax
2016-03-10 16:41   ` Charles Keepax
2016-03-11  7:48 ` [PATCH 1/4] ASoC: compress: Pass error out of soc_compr_pointer Vinod Koul
2016-03-11 10:04   ` Charles Keepax
2016-03-11 10:25     ` Takashi Iwai
2016-03-11 10:41       ` Vinod Koul
2016-03-11 10:37     ` Vinod Koul
2016-03-11 10:39       ` Takashi Iwai
2016-03-11 11:13         ` Charles Keepax
2016-03-11 11:14         ` Vinod Koul
2016-03-21 13:07           ` Charles Keepax
2016-06-22 15:29 ` Applied "ASoC: compress: Pass error out of soc_compr_pointer" to the asoc tree Mark Brown

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160311075400.GW11154@localhost \
    --to=vinod.koul@intel.com \
    --cc=alsa-devel@alsa-project.org \
    --cc=broonie@kernel.org \
    --cc=ckeepax@opensource.wolfsonmicro.com \
    --cc=lgirdwood@gmail.com \
    --cc=patches@opensource.wolfsonmicro.com \
    --cc=tiwai@suse.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).