On Tue, Nov 10, 2026 at 8:07 PM Stefan Ghetu <[email protected]> wrote:
>
> asrc_read_last_fifo() checks the FIFO fill level, a number of frames,
> against a length in bytes, and ignores the frames already drained by
> previous iterations of its retry loop. With an output length close to
> the 512 KiB buffer size, which userspace controls through the task input
> size and formats, the drain writes past the end of the output buffer:
> 312 bytes for 10 channels of S24_LE with 8 frames left in the FIFO.
> 8-bit formats are also stored as 3 bytes per sample.
>
> Check the space needed by all drained frames in bytes, and add a 1-byte
> path for 8-bit formats.
>
> Fixes: 24a01710f627 ("ASoC: fsl_asrc_m2m: Add memory to memory function")
> Signed-off-by: Stefan Ghetu <[email protected]>
> ---
>  sound/soc/fsl/fsl_asrc_m2m.c | 18 ++++++++++--------
>  1 file changed, 10 insertions(+), 8 deletions(-)
>
> diff --git a/sound/soc/fsl/fsl_asrc_m2m.c b/sound/soc/fsl/fsl_asrc_m2m.c
> index 58101ce07c9f..cadfebb12e7c 100644
> --- a/sound/soc/fsl/fsl_asrc_m2m.c
> +++ b/sound/soc/fsl/fsl_asrc_m2m.c
> @@ -53,21 +53,26 @@ static void asrc_read_last_fifo(struct fsl_asrc_pair 
> *pair, void *dma_vaddr, u32
>  {
>         struct fsl_asrc *asrc = pair->asrc;
>         enum asrc_pair_index index = pair->index;
> -       u32 i, reg, size, t_size = 0, width;
> +       u32 i, reg, size, t_size = 0, width, frame_bytes;
>         u32 *reg32 = NULL;
>         u16 *reg16 = NULL;
>         u8  *reg24 = NULL;
> +       u8  *reg8 = NULL;

The asrc doesn't support 8bit output. so don't need to add reg8 here.

Best regards
Shengjiu Wang
>
>         width = snd_pcm_format_physical_width(pair->sample_format[OUT]);
>         if (width == 32)
>                 reg32 = dma_vaddr + *length;
>         else if (width == 16)
>                 reg16 = dma_vaddr + *length;
> +       else if (width == 8)
> +               reg8 = dma_vaddr + *length;
>         else
>                 reg24 = dma_vaddr + *length;
> +
> +       frame_bytes = pair->channels * width / 8;
>  retry:
>         size = asrc->get_output_fifo_size(pair);
> -       if (size + *length > ASRC_M2M_BUFFER_SIZE)
> +       if (*length + (t_size + size) * frame_bytes > ASRC_M2M_BUFFER_SIZE)
>                 goto end;
>
>         for (i = 0; i < size * pair->channels; i++) {
> @@ -76,6 +81,8 @@ static void asrc_read_last_fifo(struct fsl_asrc_pair *pair, 
> void *dma_vaddr, u32
>                         *reg32++ = reg;
>                 } else if (reg16) {
>                         *reg16++ = (u16)reg;
> +               } else if (reg8) {
> +                       *reg8++ = (u8)reg;
>                 } else {
>                         *reg24++ = (u8)reg;
>                         *reg24++ = (u8)(reg >> 8);
> @@ -89,12 +96,7 @@ static void asrc_read_last_fifo(struct fsl_asrc_pair 
> *pair, void *dma_vaddr, u32
>                 goto retry;
>  end:
>         /* Update payload length */
> -       if (reg32)
> -               *length += t_size * pair->channels * 4;
> -       else if (reg16)
> -               *length += t_size * pair->channels * 2;
> -       else
> -               *length += t_size * pair->channels * 3;
> +       *length += t_size * frame_bytes;
>  }
>
>  /* config dma channel */
> --
> 2.53.0
>

Reply via email to