From 0cd95da1b3259cc0b73b54b2ece2e486b681d56b Mon Sep 17 00:00:00 2001 From: Slawomir Blauciak Date: Wed, 9 Jan 2019 13:55:36 +0100 Subject: [PATCH] dma: link tx timeout This is to prevent FW from getting stuck in case of anomalous situations such as DMA taking too long to copy the data. Signed-off-by: Slawomir Blauciak --- src/drivers/intel/cavs/hda-dma.c | 31 +++++++++++++++++-- .../apollolake/include/platform/platform.h | 6 ++++ .../baytrail/include/platform/platform.h | 6 ++++ .../cannonlake/include/platform/platform.h | 6 ++++ .../haswell/include/platform/platform.h | 6 ++++ .../icelake/include/platform/platform.h | 6 ++++ .../suecreek/include/platform/platform.h | 6 ++++ 7 files changed, 64 insertions(+), 3 deletions(-) diff --git a/src/drivers/intel/cavs/hda-dma.c b/src/drivers/intel/cavs/hda-dma.c index bcaf7627bc55..d4011743ecd9 100644 --- a/src/drivers/intel/cavs/hda-dma.c +++ b/src/drivers/intel/cavs/hda-dma.c @@ -385,10 +385,31 @@ static void hda_dma_post_copy(struct dma *dma, struct hda_chan_data *chan) pm_runtime_put(PM_RUNTIME_HOST_DMA_L1, 0); } +static int hda_dma_tx_wait(struct dma *dma, struct hda_chan_data *chan, + int min_bytes, uint32_t timeout_us) +{ + uint64_t deadline = platform_timer_get(platform_timer) + + clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, 1) * + timeout_us / 1000; + + while (hda_dma_get_free_size(dma, chan->index) < min_bytes) { + if (deadline < platform_timer_get(platform_timer)) { + trace_hddma_error("hda-dmac: %d tx timeout", + dma->plat_data.id); + return -ETIME; + } + + idelay(PLATFORM_DEFAULT_DELAY); + } + + return 0; +} + static int hda_dma_link_copy_ch(struct dma *dma, struct hda_chan_data *chan, int bytes) { uint32_t dgcs = 0; + int ret = 0; tracev_hddma("hda-dmac: %d channel %d -> copy 0x%x bytes", dma->plat_data.id, chan->index, bytes); @@ -403,8 +424,11 @@ static int hda_dma_link_copy_ch(struct dma *dma, struct hda_chan_data *chan, /* make sure that previous transfer is complete (playback only) */ if (chan->direction == DMA_DIR_MEM_TO_DEV) { - while (hda_dma_get_free_size(dma, chan->index) < bytes) - idelay(PLATFORM_DEFAULT_DELAY); + ret = hda_dma_tx_wait(dma, chan, bytes, + PLATFORM_LINK_DMA_TIMEOUT); + + if (ret) + goto fail; } /* @@ -417,7 +441,8 @@ static int hda_dma_link_copy_ch(struct dma *dma, struct hda_chan_data *chan, hda_dma_get_dbg_vals(chan, HDA_DBG_POST, HDA_DBG_LINK); hda_dma_ptr_trace(chan, "link copy", HDA_DBG_LINK); - return 0; +fail: + return ret; } static int hda_dma_host_copy_ch(struct dma *dma, struct hda_chan_data *chan, diff --git a/src/platform/apollolake/include/platform/platform.h b/src/platform/apollolake/include/platform/platform.h index 69bbba2cbc05..6ab7dc77fb1d 100644 --- a/src/platform/apollolake/include/platform/platform.h +++ b/src/platform/apollolake/include/platform/platform.h @@ -90,6 +90,12 @@ struct sof; /* DMA host transfer timeouts in microseconds */ #define PLATFORM_HOST_DMA_TIMEOUT 50 +/* DMA link transfer timeouts in microseconds + * TODO: timeout should be reduced + * (DMA might needs some further changes to do that) + */ +#define PLATFORM_LINK_DMA_TIMEOUT 1000 + /* WorkQ window size in microseconds */ #define PLATFORM_WORKQ_WINDOW 2000 diff --git a/src/platform/baytrail/include/platform/platform.h b/src/platform/baytrail/include/platform/platform.h index 5addc409c35f..1ae1378097a3 100644 --- a/src/platform/baytrail/include/platform/platform.h +++ b/src/platform/baytrail/include/platform/platform.h @@ -88,6 +88,12 @@ struct sof; /* DMA host transfer timeouts in microseconds */ #define PLATFORM_HOST_DMA_TIMEOUT 50 +/* DMA link transfer timeouts in microseconds + * TODO: timeout should be reduced + * (DMA might needs some further changes to do that) + */ +#define PLATFORM_LINK_DMA_TIMEOUT 1000 + /* WorkQ window size in microseconds */ #define PLATFORM_WORKQ_WINDOW 2000 diff --git a/src/platform/cannonlake/include/platform/platform.h b/src/platform/cannonlake/include/platform/platform.h index 8eb4c9a479cd..9e0bc4bed928 100644 --- a/src/platform/cannonlake/include/platform/platform.h +++ b/src/platform/cannonlake/include/platform/platform.h @@ -100,6 +100,12 @@ struct sof; /* DMA host transfer timeouts in microseconds */ #define PLATFORM_HOST_DMA_TIMEOUT 50 +/* DMA link transfer timeouts in microseconds + * TODO: timeout should be reduced + * (DMA might needs some further changes to do that) + */ +#define PLATFORM_LINK_DMA_TIMEOUT 1000 + /* WorkQ window size in microseconds */ #define PLATFORM_WORKQ_WINDOW 2000 diff --git a/src/platform/haswell/include/platform/platform.h b/src/platform/haswell/include/platform/platform.h index 01fb33b298ce..0d2a4a002371 100644 --- a/src/platform/haswell/include/platform/platform.h +++ b/src/platform/haswell/include/platform/platform.h @@ -87,6 +87,12 @@ struct sof; /* DMA host transfer timeouts in microseconds */ #define PLATFORM_HOST_DMA_TIMEOUT 50 +/* DMA link transfer timeouts in microseconds + * TODO: timeout should be reduced + * (DMA might needs some further changes to do that) + */ +#define PLATFORM_LINK_DMA_TIMEOUT 1000 + /* WorkQ window size in microseconds */ #define PLATFORM_WORKQ_WINDOW 2000 diff --git a/src/platform/icelake/include/platform/platform.h b/src/platform/icelake/include/platform/platform.h index dc82cfac4ecb..ea9e74646041 100644 --- a/src/platform/icelake/include/platform/platform.h +++ b/src/platform/icelake/include/platform/platform.h @@ -100,6 +100,12 @@ struct sof; /* DMA host transfer timeouts in microseconds */ #define PLATFORM_HOST_DMA_TIMEOUT 50 +/* DMA link transfer timeouts in microseconds + * TODO: timeout should be reduced + * (DMA might needs some further changes to do that) + */ +#define PLATFORM_LINK_DMA_TIMEOUT 1000 + /* WorkQ window size in microseconds */ #define PLATFORM_WORKQ_WINDOW 2000 diff --git a/src/platform/suecreek/include/platform/platform.h b/src/platform/suecreek/include/platform/platform.h index 8e0fa1050d1c..ac20ec6fcebf 100644 --- a/src/platform/suecreek/include/platform/platform.h +++ b/src/platform/suecreek/include/platform/platform.h @@ -100,6 +100,12 @@ struct sof; /* DMA host transfer timeouts in microseconds */ #define PLATFORM_HOST_DMA_TIMEOUT 50 +/* DMA link transfer timeouts in microseconds + * TODO: timeout should be reduced + * (DMA might needs some further changes to do that) + */ +#define PLATFORM_LINK_DMA_TIMEOUT 1000 + /* WorkQ window size in microseconds */ #define PLATFORM_WORKQ_WINDOW 2000