All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Cássio Gabriel" <cassiogabrielcontato@gmail.com>
To: Takashi Iwai <tiwai@suse.com>, Vinod Koul <vkoul@kernel.org>,
	 Mark Brown <broonie@kernel.org>,
	Jaroslav Kysela <perex@perex.cz>
Cc: linux-sound@vger.kernel.org, linux-kernel@vger.kernel.org,
	"Cássio Gabriel" <cassiogabrielcontato@gmail.com>
Subject: [PATCH 2/2] ALSA: compress: Propagate real pointer errors in avail paths
Date: Tue, 14 Apr 2026 13:47:54 -0300	[thread overview]
Message-ID: <20260414-alsa-compress-pointer-avail-errors-v1-2-f5a1a8b1dfba@gmail.com> (raw)
In-Reply-To: <20260414-alsa-compress-pointer-avail-errors-v1-0-f5a1a8b1dfba@gmail.com>

Commit 61327f3d817c ("ALSA: compress: Pay attention if drivers
error out retrieving pointers") made snd_compr_update_tstamp()
return driver pointer() failures, but snd_compr_calc_avail()
still ignores that status and continues with stale runtime
counters.

The fallback for an unsupported pointer callback remains
intentional, so keep ignoring -EOPNOTSUPP there. Propagate
real pointer-refresh failures instead.

This makes SNDRV_COMPRESS_AVAIL, read() and write() fail
immediately on real pointer errors, and makes poll() report
EPOLLERR instead of continuing with stale availability data.
snd_compr_tstamp() already propagates the same errors, so
this also restores consistency between the timestamp and
avail paths.

Fixes: 61327f3d817c ("ALSA: compress: Pay attention if drivers error out retrieving pointers")
Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
---
 sound/core/compress_offload.c | 53 ++++++++++++++++++++++++++++++-------------
 1 file changed, 37 insertions(+), 16 deletions(-)

diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
index e3239c739d34..5a125329d5b7 100644
--- a/sound/core/compress_offload.c
+++ b/sound/core/compress_offload.c
@@ -207,18 +207,23 @@ 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,
-				   struct snd_compr_avail64 *avail)
+static int snd_compr_calc_avail(struct snd_compr_stream *stream,
+				struct snd_compr_avail64 *avail)
 {
+	int ret;
+
 	memset(avail, 0, sizeof(*avail));
-	snd_compr_update_tstamp(stream, &avail->tstamp);
-	/* Still need to return avail even if tstamp can't be filled in */
+	ret = snd_compr_update_tstamp(stream, &avail->tstamp);
+	if (ret < 0 && ret != -EOPNOTSUPP)
+		return ret;
+	/* Still need to return avail when no timestamp is available */
 
 	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 %llu, DSP consumed %llu\n",
 		 stream->runtime->total_bytes_available,
@@ -227,11 +232,12 @@ 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;
 		} else {
 			pr_debug("both pointers are same, returning no avail\n");
-			return 0;
+			avail->avail = 0;
 		}
+		return 0;
 	}
 
 	avail->avail = stream->runtime->total_bytes_available -
@@ -240,14 +246,21 @@ 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 %zu\n", (size_t)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_ret)
 {
 	struct snd_compr_avail64 avail;
+	int ret;
 
-	return snd_compr_calc_avail(stream, &avail);
+	ret = snd_compr_calc_avail(stream, &avail);
+	if (ret < 0)
+		return ret;
+
+	*avail_ret = avail.avail;
+	return 0;
 }
 
 static void snd_compr_avail32_from_64(struct snd_compr_avail *avail32,
@@ -262,15 +275,16 @@ static int snd_compr_ioctl_avail(struct snd_compr_stream *stream,
 {
 	struct snd_compr_avail64 ioctl_avail64;
 	struct snd_compr_avail ioctl_avail32;
-	size_t avail;
 	const void *copy_from = &ioctl_avail64;
 	size_t copy_size = sizeof(ioctl_avail64);
+	int ret;
 
 	if (stream->direction == SND_COMPRESS_ACCEL)
 		return -EBADFD;
 
-	avail = snd_compr_calc_avail(stream, &ioctl_avail64);
-	ioctl_avail64.avail = avail;
+	ret = snd_compr_calc_avail(stream, &ioctl_avail64);
+	if (ret < 0)
+		return ret;
 	if (is_32bit) {
 		snd_compr_avail32_from_64(&ioctl_avail32, &ioctl_avail64);
 		copy_from = &ioctl_avail32;
@@ -346,7 +360,9 @@ static ssize_t snd_compr_write(struct file *f, const char __user *buf,
 		return -EBADFD;
 	}
 
-	avail = snd_compr_get_avail(stream);
+	retval = snd_compr_get_avail(stream, &avail);
+	if (retval < 0)
+		return retval;
 	pr_debug("avail returned %lu\n", (unsigned long)avail);
 	/* calculate how much we can write to buffer */
 	if (avail > count)
@@ -402,7 +418,9 @@ static ssize_t snd_compr_read(struct file *f, char __user *buf,
 		return -EPIPE;
 	}
 
-	avail = snd_compr_get_avail(stream);
+	retval = snd_compr_get_avail(stream, &avail);
+	if (retval < 0)
+		return retval;
 	pr_debug("avail returned %lu\n", (unsigned long)avail);
 	/* calculate how much we can read from buffer */
 	if (avail > count)
@@ -437,6 +455,7 @@ static __poll_t snd_compr_poll(struct file *f, poll_table *wait)
 	struct snd_compr_stream *stream;
 	struct snd_compr_runtime *runtime;
 	size_t avail;
+	int ret;
 	__poll_t retval = 0;
 
 	if (snd_BUG_ON(!data))
@@ -471,7 +490,9 @@ static __poll_t snd_compr_poll(struct file *f, poll_table *wait)
 	}
 #endif
 
-	avail = snd_compr_get_avail(stream);
+	ret = snd_compr_get_avail(stream, &avail);
+	if (ret < 0)
+		return snd_compr_get_poll(stream) | EPOLLERR;
 	pr_debug("avail is %lu\n", (unsigned long)avail);
 	/* check if we have at least one fragment to fill */
 	switch (runtime->state) {

-- 
2.53.0


  parent reply	other threads:[~2026-04-14 16:48 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-14 16:47 [PATCH 0/2] ALSA: compress: clean up pointer errno handling and fix avail errors Cássio Gabriel
2026-04-14 16:47 ` [PATCH 1/2] ALSA: compress: Use EOPNOTSUPP for missing pointer callbacks Cássio Gabriel
2026-04-14 16:47 ` Cássio Gabriel [this message]
2026-04-14 16:53   ` [PATCH 2/2] ALSA: compress: Propagate real pointer errors in avail paths Mark Brown
2026-04-14 17:45     ` Cássio Gabriel Monteiro Pires
2026-04-15 14:20       ` Takashi Iwai
2026-04-15 19:29         ` Cássio Gabriel Monteiro Pires

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=20260414-alsa-compress-pointer-avail-errors-v1-2-f5a1a8b1dfba@gmail.com \
    --to=cassiogabrielcontato@gmail.com \
    --cc=broonie@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-sound@vger.kernel.org \
    --cc=perex@perex.cz \
    --cc=tiwai@suse.com \
    --cc=vkoul@kernel.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.