On Fri, 15 Oct 2021 21:59:30 +0200, Pierre-Louis Bossart wrote: > > When the hardware can only deal with a monotonically increasing > appl_ptr, this flag can be set. > > In case the application requests a rewind, be it with a > snd_pcm_rewind() or with a direct change of a mmap'ed pointer followed > by a SNDRV_PCM_IOCTL_SYNC_PTR, this patch checks if a rewind > occurred and returns an error. > > Credits to Takashi Iwai for identifying the path with SYNC_PTR and > suggesting the pointer checks. > > Suggested-by: Takashi Iwai <tiwai@xxxxxxx> > Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@xxxxxxxxxxxxxxx> > Reviewed-by: Ranjani Sridharan <ranjani.sridharan@xxxxxxxxxxxxxxx> > Reviewed-by: Kai Vehmanen <kai.vehmanen@xxxxxxxxx> Reviewed-by: Takashi Iwai <tiwai@xxxxxxx> thanks, Takashi > --- > include/uapi/sound/asound.h | 2 +- > sound/core/pcm_lib.c | 14 ++++++++++++++ > 2 files changed, 15 insertions(+), 1 deletion(-) > > diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h > index 5859ca0a1439..59fcf39f022e 100644 > --- a/include/uapi/sound/asound.h > +++ b/include/uapi/sound/asound.h > @@ -300,7 +300,7 @@ typedef int __bitwise snd_pcm_subformat_t; > #define SNDRV_PCM_INFO_HAS_LINK_ESTIMATED_ATIME 0x04000000 /* report estimated link audio time */ > #define SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME 0x08000000 /* report synchronized audio/system time */ > #define SNDRV_PCM_INFO_EXPLICIT_SYNC 0x10000000 /* needs explicit sync of pointers and data */ > - > +#define SNDRV_PCM_INFO_NO_REWINDS 0x20000000 /* hardware can only support monotonic changes of appl_ptr */ > #define SNDRV_PCM_INFO_DRAIN_TRIGGER 0x40000000 /* internal kernel flag - trigger in drain */ > #define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000 /* internal kernel flag - FIFO size is in frames */ > > diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c > index ec53a3e7cf35..1d3927aa3dd8 100644 > --- a/sound/core/pcm_lib.c > +++ b/sound/core/pcm_lib.c > @@ -2127,6 +2127,7 @@ int pcm_lib_apply_appl_ptr(struct snd_pcm_substream *substream, > { > struct snd_pcm_runtime *runtime = substream->runtime; > snd_pcm_uframes_t old_appl_ptr = runtime->control->appl_ptr; > + snd_pcm_sframes_t diff; > int ret; > > if (old_appl_ptr == appl_ptr) > @@ -2134,6 +2135,19 @@ int pcm_lib_apply_appl_ptr(struct snd_pcm_substream *substream, > > if (appl_ptr >= runtime->boundary) > return -EINVAL; > + /* > + * check if a rewind is requested by the application > + */ > + if (substream->runtime->info & SNDRV_PCM_INFO_NO_REWINDS) { > + diff = appl_ptr - old_appl_ptr; > + if (diff >= 0) { > + if (diff > runtime->buffer_size) > + return -EINVAL; > + } else { > + if (runtime->boundary + diff > runtime->buffer_size) > + return -EINVAL; > + } > + } > > runtime->control->appl_ptr = appl_ptr; > if (substream->ops->ack) { > -- > 2.25.1 >