Query about xrun on usb/pcm
Carl Hetherington
lists at carlh.net
Wed Nov 30 23:37:39 CET 2022
Hi Takashi,
> > Thanks for the suggestion. I experimented a little with this, but I
> > think the problem I'm seeing is that (even if the application knows it
> > should retry the snd_pcm_prepare() step) we still end up with an endpoint
> > in EP_STATE_STOPPING while the corresponding stop_operating flag is 0.
>
> Ah, I guess that's a fallout in the logic. When XRUN happens at start
> -- receiving an -EPIPE error at snd_pcm_do_start() -- then the patch
> sets the XRUN state. This assumed that the stream gets stopped the
> following snd_pcm_undo_start() call. Indeed it does stop but there we
> forgot setting stop_operating flag unlike what snd_pcm_stop() does.
Thanks for the hint. I checked it out again, and in fact I'm seeing the
-EPIPE come back from snd_pcm_do_prepare(). It starts its sync-stop,
another xrun comes in (as we talked about before), it tries to
start_endpoints() and that fails.
A fairly similar thing to what you suggested seems to work for me:
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index f38c2e5e9a29..0b61943cca98 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1948,9 +1948,17 @@ static void snd_pcm_post_prepare(struct snd_pcm_substream *substream,
snd_pcm_set_state(substream, SNDRV_PCM_STATE_PREPARED);
}
+
+static void snd_pcm_undo_prepare(struct snd_pcm_substream *substream,
+ snd_pcm_state_t state)
+{
+ substream->runtime->stop_operating = true;
+}
+
static const struct action_ops snd_pcm_action_prepare = {
.pre_action = snd_pcm_pre_prepare,
.do_action = snd_pcm_do_prepare,
+ .undo_action = snd_pcm_undo_prepare,
.post_action = snd_pcm_post_prepare
};
Can you see any problems with that? In the application code I do need
to re-try the snd_pcm_prepare() if one fails with -EPIPE, but with this
undo step the second snd_pcm_prepare() is able to recover the endpoint
states, instead of hitting this problem where it tries to start things
that are STOPPING, but also won't set things to STOPPED because
stop_operating is false.
Thanks and best regards,
Carl
More information about the Alsa-devel
mailing list