All tasks of a stream share one pair and one set of DMA channels, and
get_caps() advertises a single fragment, but the compress core allows
up to 64 tasks. A second task requests the pair again and overwrites the
DMA channels. Freeing both tasks then releases the same channels twice
and leaves a stale asrc->pair[] entry after close.
Return -EBUSY from task_create() while a task exists, and clear the DMA
channel pointers once they are released.
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 | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/sound/soc/fsl/fsl_asrc_m2m.c b/sound/soc/fsl/fsl_asrc_m2m.c
index cadfebb12e7c..2e91073f14f9 100644
--- a/sound/soc/fsl/fsl_asrc_m2m.c
+++ b/sound/soc/fsl/fsl_asrc_m2m.c
@@ -471,6 +471,10 @@ static int fsl_asrc_m2m_comp_task_create(struct
snd_compr_stream *stream,
struct dma_chan *tmp_chan;
int ret;
+ /* All tasks share the pair and DMA channels: one task at a time */
+ if (pair->dma_chan[IN])
+ return -EBUSY;
+
exp_info_in.ops = &fsl_asrc_m2m_dma_buf_ops;
exp_info_in.size = ASRC_M2M_BUFFER_SIZE;
exp_info_in.flags = O_RDWR;
@@ -527,6 +531,7 @@ static int fsl_asrc_m2m_comp_task_create(struct
snd_compr_stream *stream,
err_dma_channel_out:
dma_release_channel(pair->dma_chan[IN]);
+ pair->dma_chan[IN] = NULL;
err_dma_channel_in:
if (asrc->m2m_unprepare)
asrc->m2m_unprepare(pair);
@@ -571,6 +576,8 @@ static int fsl_asrc_m2m_comp_task_free(struct
snd_compr_stream *stream,
dma_release_channel(pair->dma_chan[IN]);
if (pair->dma_chan[OUT])
dma_release_channel(pair->dma_chan[OUT]);
+ pair->dma_chan[IN] = NULL;
+ pair->dma_chan[OUT] = NULL;
return 0;
}
--
2.53.0