From 03a8890ee098e00f8b3c89c2d7f134ed4b89b68c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Lothar=20Wa=C3=9Fmann?= Date: Wed, 3 Sep 2014 13:57:07 +0200 Subject: [PATCH] MX28: DMA: make the DMA timeout configurable Use the default value from commit 1375f044d96f "MX28: DMA: Prolong the DMA timeout", but let users change it depending on the amount of data to be transferred and the expected data rate. --- arch/arm/include/asm/imx-common/dma.h | 3 ++ drivers/dma/apbh_dma.c | 56 +++++++++++++++++++++++++-- 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/arch/arm/include/asm/imx-common/dma.h b/arch/arm/include/asm/imx-common/dma.h index 5f516ef6e0..14a0c12ddc 100644 --- a/arch/arm/include/asm/imx-common/dma.h +++ b/arch/arm/include/asm/imx-common/dma.h @@ -150,11 +150,14 @@ struct mxs_dma_chan { unsigned int pending_num; struct list_head active; struct list_head done; + unsigned long timeout; }; struct mxs_dma_desc *mxs_dma_desc_alloc(void); void mxs_dma_desc_free(struct mxs_dma_desc *); int mxs_dma_desc_append(int channel, struct mxs_dma_desc *pdesc); +int mxs_dma_set_timeout(int channel, unsigned long timeout); +unsigned long mxs_dma_get_timeout(int channel); int mxs_dma_go(int chan); void mxs_dma_init(void); diff --git a/drivers/dma/apbh_dma.c b/drivers/dma/apbh_dma.c index 042e0ef5fb..eab87bc9f4 100644 --- a/drivers/dma/apbh_dma.c +++ b/drivers/dma/apbh_dma.c @@ -290,6 +290,7 @@ static int mxs_dma_request(int channel) pchan->flags |= MXS_DMA_FLAGS_ALLOCATED; pchan->active_num = 0; pchan->pending_num = 0; + pchan->timeout = 10000000; INIT_LIST_HEAD(&pchan->active); INIT_LIST_HEAD(&pchan->done); @@ -327,6 +328,44 @@ int mxs_dma_release(int channel) return 0; } +/* + * Set the timeout for any DMA operation started with mxs_dma_go() + * The timeout value given is in milliseconds + */ +int mxs_dma_set_timeout(int channel, unsigned long timeout) +{ + int ret; + struct mxs_dma_chan *pchan; + + ret = mxs_dma_validate_chan(channel); + if (ret) + return ret; + + pchan = &mxs_dma_channels[channel]; + + if (pchan->flags & MXS_DMA_FLAGS_BUSY) + return -EBUSY; + + if (timeout > ~0UL / 1000) + return -EINVAL; + + pchan->timeout = timeout; + return 0; +} + +unsigned long mxs_dma_get_timeout(int channel) +{ + int ret; + struct mxs_dma_chan *pchan; + + ret = mxs_dma_validate_chan(channel); + if (ret) + return 0; + + pchan = &mxs_dma_channels[channel]; + return pchan->timeout; +} + /* * Allocate DMA descriptor */ @@ -513,16 +552,25 @@ static int mxs_dma_wait_complete(uint32_t timeout, unsigned int chan) */ int mxs_dma_go(int chan) { - uint32_t timeout = 10000; int ret; - + struct mxs_dma_chan *pchan; LIST_HEAD(tmp_desc_list); + ret = mxs_dma_validate_chan(chan); + if (ret) + return ret; + + pchan = &mxs_dma_channels[chan]; + mxs_dma_enable_irq(chan, 1); - mxs_dma_enable(chan); + ret = mxs_dma_enable(chan); + if (ret) { + mxs_dma_enable_irq(chan, 0); + return ret; + } /* Wait for DMA to finish. */ - ret = mxs_dma_wait_complete(timeout, chan); + ret = mxs_dma_wait_complete(pchan->timeout * 1000, chan); /* Clear out the descriptors we just ran. */ mxs_dma_finish(chan, &tmp_desc_list); -- 2.39.2