MX28: DMA: make the DMA timeout configurable
authorLothar Waßmann <LW@KARO-electronics.de>
Wed, 3 Sep 2014 11:57:07 +0000 (13:57 +0200)
committerLothar Waßmann <LW@KARO-electronics.de>
Wed, 3 Sep 2014 11:57:07 +0000 (13:57 +0200)
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
drivers/dma/apbh_dma.c

index 5f516ef..14a0c12 100644 (file)
@@ -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);
index 042e0ef..eab87bc 100644 (file)
@@ -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);
@@ -328,6 +329,44 @@ int mxs_dma_release(int channel)
 }
 
 /*
+ * 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
  */
 struct mxs_dma_desc *mxs_dma_desc_alloc(void)
@@ -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);