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
>