Skip to content

Commit

Permalink
drivers: dma: intel-adsp-hda: modify stop dma logic
Browse files Browse the repository at this point in the history
Commit b2eaa6448076 ("drivers: dma: intel-adsp-hda: add delay to stop
host dma") added a wait on GBUSY state to host DMA stop.

This is problematic as in some case (like SOF chain-DMA usage),
the host DMA side RUN bit is not cleared when intel_adsp_hda_dma_stop()
is called. It is not possible to wait on GBUSY bit as there are
valid cases where it can remain set.

Address the original problem described in SOF bug zephyrproject-rtos#8686 and add a
polling check for intel_adsp_hda_is_enabled(). As per the bug
description, in some cases the GEN/FIFORDY bits are not cleared
immediately and if a new call to intel_adsp_hda_dma_stop() is made, the
PM refcounting will go haywire.

Link: thesofproject/sof#8686
Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
(cherry picked from commit 00d4661)
  • Loading branch information
kv2019i committed Mar 5, 2024
1 parent 369241d commit 576924d
Showing 1 changed file with 3 additions and 6 deletions.
9 changes: 3 additions & 6 deletions drivers/dma/dma_intel_adsp_hda.c
Original file line number Diff line number Diff line change
Expand Up @@ -326,12 +326,9 @@ int intel_adsp_hda_dma_stop(const struct device *dev, uint32_t channel)

intel_adsp_hda_disable(cfg->base, cfg->regblock_size, channel);

/* host dma needs some cycles to completely stop */
if (cfg->direction == HOST_TO_MEMORY || cfg->direction == MEMORY_TO_HOST) {
if (!WAIT_FOR(!(*DGCS(cfg->base, cfg->regblock_size, channel) & DGCS_GBUSY), 1000,
k_busy_wait(1))) {
return -EBUSY;
}
if (!WAIT_FOR(!intel_adsp_hda_is_enabled(cfg->base, cfg->regblock_size, channel), 1000,
k_busy_wait(1))) {
return -EBUSY;
}

return pm_device_runtime_put(dev);
Expand Down

0 comments on commit 576924d

Please sign in to comment.