ALSA: pcm: Improved XRUN handling for indirect PCM helpers

As PCM ack callback may handle the XRUN situation gracefully now,
change the indirect PCM helpers to give a proper error (-EPIPE).
Also, change the pointer callback helpers to deal with the XRUN error
properly, too.

This requires the PCM core change by the commit 8c721c53dd
("ALSA: usb-audio: Fix recursive locking at XRUN during syncing").

Link: https://lore.kernel.org/r/20230323065237.5062-2-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Takashi Iwai 2023-03-23 07:52:35 +01:00
parent a7a0dcdff4
commit 0146878cf2

View File

@ -44,7 +44,7 @@ snd_pcm_indirect_playback_transfer(struct snd_pcm_substream *substream,
if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2)) if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
diff += runtime->boundary; diff += runtime->boundary;
if (diff < 0) if (diff < 0)
return -EINVAL; return -EPIPE;
rec->sw_ready += (int)frames_to_bytes(runtime, diff); rec->sw_ready += (int)frames_to_bytes(runtime, diff);
rec->appl_ptr = appl_ptr; rec->appl_ptr = appl_ptr;
} }
@ -83,6 +83,8 @@ snd_pcm_indirect_playback_pointer(struct snd_pcm_substream *substream,
struct snd_pcm_indirect *rec, unsigned int ptr) struct snd_pcm_indirect *rec, unsigned int ptr)
{ {
int bytes = ptr - rec->hw_io; int bytes = ptr - rec->hw_io;
int err;
if (bytes < 0) if (bytes < 0)
bytes += rec->hw_buffer_size; bytes += rec->hw_buffer_size;
rec->hw_io = ptr; rec->hw_io = ptr;
@ -90,8 +92,11 @@ snd_pcm_indirect_playback_pointer(struct snd_pcm_substream *substream,
rec->sw_io += bytes; rec->sw_io += bytes;
if (rec->sw_io >= rec->sw_buffer_size) if (rec->sw_io >= rec->sw_buffer_size)
rec->sw_io -= rec->sw_buffer_size; rec->sw_io -= rec->sw_buffer_size;
if (substream->ops->ack) if (substream->ops->ack) {
substream->ops->ack(substream); err = substream->ops->ack(substream);
if (err == -EPIPE)
return SNDRV_PCM_POS_XRUN;
}
return bytes_to_frames(substream->runtime, rec->sw_io); return bytes_to_frames(substream->runtime, rec->sw_io);
} }
@ -112,7 +117,7 @@ snd_pcm_indirect_capture_transfer(struct snd_pcm_substream *substream,
if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2)) if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
diff += runtime->boundary; diff += runtime->boundary;
if (diff < 0) if (diff < 0)
return -EINVAL; return -EPIPE;
rec->sw_ready -= frames_to_bytes(runtime, diff); rec->sw_ready -= frames_to_bytes(runtime, diff);
rec->appl_ptr = appl_ptr; rec->appl_ptr = appl_ptr;
} }
@ -152,6 +157,8 @@ snd_pcm_indirect_capture_pointer(struct snd_pcm_substream *substream,
{ {
int qsize; int qsize;
int bytes = ptr - rec->hw_io; int bytes = ptr - rec->hw_io;
int err;
if (bytes < 0) if (bytes < 0)
bytes += rec->hw_buffer_size; bytes += rec->hw_buffer_size;
rec->hw_io = ptr; rec->hw_io = ptr;
@ -162,8 +169,11 @@ snd_pcm_indirect_capture_pointer(struct snd_pcm_substream *substream,
rec->sw_io += bytes; rec->sw_io += bytes;
if (rec->sw_io >= rec->sw_buffer_size) if (rec->sw_io >= rec->sw_buffer_size)
rec->sw_io -= rec->sw_buffer_size; rec->sw_io -= rec->sw_buffer_size;
if (substream->ops->ack) if (substream->ops->ack) {
substream->ops->ack(substream); err = substream->ops->ack(substream);
if (err == -EPIPE)
return SNDRV_PCM_POS_XRUN;
}
return bytes_to_frames(substream->runtime, rec->sw_io); return bytes_to_frames(substream->runtime, rec->sw_io);
} }