From 6a581d8a75e4e05edee2a14413d829f182ff2112 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Thu, 22 May 2025 14:19:41 +0300 Subject: [PATCH 1/2] drivers: dma: sdma: Fix noise issue with pause/resume Each time we configure an SDMA channel we also compute the total allocated DMA buffer length but we assume is initialized with zero. This is true each time a channel is requested. But if there are multiple calls to configure without releasing the channel the buffer length is not correctly computed. So, we need to initialize it with zero each time we reconfigure the dma channel. Signed-off-by: Daniel Baluta --- drivers/dma/dma_nxp_sdma.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/dma/dma_nxp_sdma.c b/drivers/dma/dma_nxp_sdma.c index e6cd0e9dec825..fb91605d1920f 100644 --- a/drivers/dma/dma_nxp_sdma.c +++ b/drivers/dma/dma_nxp_sdma.c @@ -237,6 +237,8 @@ static void dma_nxp_sdma_setup_bd(const struct device *dev, uint32_t channel, chan_data = &dev_data->chan[channel]; + chan_data->capacity = 0; + /* initialize bd pool */ chan_data->bd_pool = &dev_data->bd_pool[channel][0]; chan_data->bd_count = config->block_count; From 4fde6af8b4269b696ce38ef4a988f42386289583 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Mon, 26 May 2025 15:34:15 +0300 Subject: [PATCH 2/2] drivers: dma: sdma: Make access to DMA channel stats atomic DMA channel stats like pending_length or free is not protected and can be modified in parallel by a consumer and a producer. This can result in non-atomic updates which in turn will result in using stale data. Fix this by making regions of code accessing dma stats atomic. Fixes: e94c86f3951 ("drivers: dma: Add initial support for NXP SDMA") Signed-off-by: Daniel Baluta --- drivers/dma/dma_nxp_sdma.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/dma/dma_nxp_sdma.c b/drivers/dma/dma_nxp_sdma.c index fb91605d1920f..51885d60f4617 100644 --- a/drivers/dma/dma_nxp_sdma.c +++ b/drivers/dma/dma_nxp_sdma.c @@ -376,11 +376,14 @@ static int dma_nxp_sdma_get_status(const struct device *dev, uint32_t channel, { struct sdma_dev_data *dev_data = dev->data; struct sdma_channel_data *chan_data; + unsigned int key; chan_data = &dev_data->chan[channel]; + key = irq_lock(); stat->free = chan_data->stat.free; stat->pending_length = chan_data->stat.pending_length; + irq_unlock(key); return 0; } @@ -390,6 +393,7 @@ static int dma_nxp_sdma_reload(const struct device *dev, uint32_t channel, uint3 { struct sdma_dev_data *dev_data = dev->data; struct sdma_channel_data *chan_data; + unsigned int key; chan_data = &dev_data->chan[channel]; @@ -397,11 +401,13 @@ static int dma_nxp_sdma_reload(const struct device *dev, uint32_t channel, uint3 return 0; } + key = irq_lock(); if (chan_data->direction == MEMORY_TO_PERIPHERAL) { dma_nxp_sdma_produce(chan_data, size); } else { dma_nxp_sdma_consume(chan_data, size); } + irq_unlock(key); return 0; }