From 830a281588fa3e0439447b92c57ae7f3bf75c01b Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Tue, 28 Nov 2023 18:28:05 +0200 Subject: [PATCH] drivers: dma: intel_adsp_gpdma: fix issue with stop and PM refcounts The DMA interface allows start and stop to be called multiple times and driver should ensure nothing bad happens if the calls are not balanced. Fix an issue where after a start-stop sequence the DMA would be powered down, and then a subsequent stop would result in a crash as driver accesses registers of a powered down hardware block. Fix the issue by handling stop without actually reading the hw registers to check channel status. Link: https://github.com/thesofproject/sof/issues/8503 Signed-off-by: Kai Vehmanen --- drivers/dma/dma_dw_common.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/dma/dma_dw_common.c b/drivers/dma/dma_dw_common.c index 0a5040980b2ff07..40410a50da0e2d4 100644 --- a/drivers/dma/dma_dw_common.c +++ b/drivers/dma/dma_dw_common.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include "dma_dw_common.h" @@ -546,6 +547,7 @@ int dw_dma_stop(const struct device *dev, uint32_t channel) const struct dw_dma_dev_cfg *const dev_cfg = dev->config; struct dw_dma_dev_data *dev_data = dev->data; struct dw_dma_chan_data *chan_data = &dev_data->chan[channel]; + enum pm_device_state pm_state; int ret = 0; if (channel >= DW_CHAN_COUNT) { @@ -553,7 +555,13 @@ int dw_dma_stop(const struct device *dev, uint32_t channel) goto out; } + /* skip if PM used and device is not active */ + ret = pm_device_state_get(dev, &pm_state); + if (!ret && pm_state != PM_DEVICE_STATE_ACTIVE) + goto out; + if (!dw_dma_is_enabled(dev, channel) && chan_data->state != DW_DMA_SUSPENDED) { + ret = 0; goto out; }