]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/dma/dma-jz4780.c
Merge tag 'wireless-drivers-for-davem-2019-10-15' of git://git.kernel.org/pub/scm...
[linux.git] / drivers / dma / dma-jz4780.c
index 7fe9309a876bde8fcb6e035dd0fd27baf464f333..cafb1cc065bb76f397541f54bb597982dbc4ece4 100644 (file)
@@ -92,6 +92,7 @@
 #define JZ_SOC_DATA_PROGRAMMABLE_DMA   BIT(1)
 #define JZ_SOC_DATA_PER_CHAN_PM                BIT(2)
 #define JZ_SOC_DATA_NO_DCKES_DCKEC     BIT(3)
+#define JZ_SOC_DATA_BREAK_LINKS                BIT(4)
 
 /**
  * struct jz4780_dma_hwdesc - descriptor structure read by the DMA controller.
@@ -355,6 +356,7 @@ static struct dma_async_tx_descriptor *jz4780_dma_prep_slave_sg(
        void *context)
 {
        struct jz4780_dma_chan *jzchan = to_jz4780_dma_chan(chan);
+       struct jz4780_dma_dev *jzdma = jz4780_dma_chan_parent(jzchan);
        struct jz4780_dma_desc *desc;
        unsigned int i;
        int err;
@@ -375,7 +377,8 @@ static struct dma_async_tx_descriptor *jz4780_dma_prep_slave_sg(
 
                desc->desc[i].dcm |= JZ_DMA_DCM_TIE;
 
-               if (i != (sg_len - 1)) {
+               if (i != (sg_len - 1) &&
+                   !(jzdma->soc_data->flags & JZ_SOC_DATA_BREAK_LINKS)) {
                        /* Automatically proceeed to the next descriptor. */
                        desc->desc[i].dcm |= JZ_DMA_DCM_LINK;
 
@@ -664,6 +667,8 @@ static enum dma_status jz4780_dma_tx_status(struct dma_chan *chan,
 static bool jz4780_dma_chan_irq(struct jz4780_dma_dev *jzdma,
                                struct jz4780_dma_chan *jzchan)
 {
+       const unsigned int soc_flags = jzdma->soc_data->flags;
+       struct jz4780_dma_desc *desc = jzchan->desc;
        uint32_t dcs;
        bool ack = true;
 
@@ -691,8 +696,11 @@ static bool jz4780_dma_chan_irq(struct jz4780_dma_dev *jzdma,
 
                                jz4780_dma_begin(jzchan);
                        } else if (dcs & JZ_DMA_DCS_TT) {
-                               vchan_cookie_complete(&jzchan->desc->vdesc);
-                               jzchan->desc = NULL;
+                               if (!(soc_flags & JZ_SOC_DATA_BREAK_LINKS) ||
+                                   (jzchan->curr_hwdesc + 1 == desc->count)) {
+                                       vchan_cookie_complete(&desc->vdesc);
+                                       jzchan->desc = NULL;
+                               }
 
                                jz4780_dma_begin(jzchan);
                        } else {
@@ -878,10 +886,8 @@ static int jz4780_dma_probe(struct platform_device *pdev)
        }
 
        ret = platform_get_irq(pdev, 0);
-       if (ret < 0) {
-               dev_err(dev, "failed to get IRQ: %d\n", ret);
+       if (ret < 0)
                return ret;
-       }
 
        jzdma->irq = ret;
 
@@ -992,6 +998,7 @@ static int jz4780_dma_remove(struct platform_device *pdev)
 static const struct jz4780_dma_soc_data jz4740_dma_soc_data = {
        .nb_channels = 6,
        .transfer_ord_max = 5,
+       .flags = JZ_SOC_DATA_BREAK_LINKS,
 };
 
 static const struct jz4780_dma_soc_data jz4725b_dma_soc_data = {