Merge tag 'dmaengine-5.4-rc1' of git://git.infradead.org/users/vkoul/slave-dma
[sfrench/cifs-2.6.git] / drivers / dma / ti / omap-dma.c
index d07c0d5de7a256388e1806afa4264e91f2f51e2d..6b6ba238b81a756b8e2e8b5c41154283a94531af 100644 (file)
@@ -91,6 +91,7 @@ struct omap_desc {
        bool using_ll;
        enum dma_transfer_direction dir;
        dma_addr_t dev_addr;
+       bool polled;
 
        int32_t fi;             /* for OMAP_DMA_SYNC_PACKET / double indexing */
        int16_t ei;             /* for double indexing */
@@ -202,6 +203,7 @@ static const unsigned es_bytes[] = {
        [CSDP_DATA_TYPE_32] = 4,
 };
 
+static bool omap_dma_filter_fn(struct dma_chan *chan, void *param);
 static struct of_dma_filter_info omap_dma_info = {
        .filter_fn = omap_dma_filter_fn,
 };
@@ -812,31 +814,22 @@ static enum dma_status omap_dma_tx_status(struct dma_chan *chan,
        dma_cookie_t cookie, struct dma_tx_state *txstate)
 {
        struct omap_chan *c = to_omap_dma_chan(chan);
-       struct virt_dma_desc *vd;
        enum dma_status ret;
        unsigned long flags;
+       struct omap_desc *d = NULL;
 
        ret = dma_cookie_status(chan, cookie, txstate);
-
-       if (!c->paused && c->running) {
-               uint32_t ccr = omap_dma_chan_read(c, CCR);
-               /*
-                * The channel is no longer active, set the return value
-                * accordingly
-                */
-               if (!(ccr & CCR_ENABLE))
-                       ret = DMA_COMPLETE;
-       }
-
-       if (ret == DMA_COMPLETE || !txstate)
+       if (ret == DMA_COMPLETE)
                return ret;
 
        spin_lock_irqsave(&c->vc.lock, flags);
-       vd = vchan_find_desc(&c->vc, cookie);
-       if (vd) {
-               txstate->residue = omap_dma_desc_size(to_omap_dma_desc(&vd->tx));
-       } else if (c->desc && c->desc->vd.tx.cookie == cookie) {
-               struct omap_desc *d = c->desc;
+       if (c->desc && c->desc->vd.tx.cookie == cookie)
+               d = c->desc;
+
+       if (!txstate)
+               goto out;
+
+       if (d) {
                dma_addr_t pos;
 
                if (d->dir == DMA_MEM_TO_DEV)
@@ -848,10 +841,31 @@ static enum dma_status omap_dma_tx_status(struct dma_chan *chan,
 
                txstate->residue = omap_dma_desc_size_pos(d, pos);
        } else {
-               txstate->residue = 0;
+               struct virt_dma_desc *vd = vchan_find_desc(&c->vc, cookie);
+
+               if (vd)
+                       txstate->residue = omap_dma_desc_size(
+                                               to_omap_dma_desc(&vd->tx));
+               else
+                       txstate->residue = 0;
        }
-       if (ret == DMA_IN_PROGRESS && c->paused)
+
+out:
+       if (ret == DMA_IN_PROGRESS && c->paused) {
                ret = DMA_PAUSED;
+       } else if (d && d->polled && c->running) {
+               uint32_t ccr = omap_dma_chan_read(c, CCR);
+               /*
+                * The channel is no longer active, set the return value
+                * accordingly and mark it as completed
+                */
+               if (!(ccr & CCR_ENABLE)) {
+                       ret = DMA_COMPLETE;
+                       omap_dma_start_desc(c);
+                       vchan_cookie_complete(&d->vd);
+               }
+       }
+
        spin_unlock_irqrestore(&c->vc.lock, flags);
 
        return ret;
@@ -1178,7 +1192,10 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_memcpy(
        d->ccr = c->ccr;
        d->ccr |= CCR_DST_AMODE_POSTINC | CCR_SRC_AMODE_POSTINC;
 
-       d->cicr = CICR_DROP_IE | CICR_FRAME_IE;
+       if (tx_flags & DMA_PREP_INTERRUPT)
+               d->cicr |= CICR_FRAME_IE;
+       else
+               d->polled = true;
 
        d->csdp = data_type;
 
@@ -1639,7 +1656,7 @@ static struct platform_driver omap_dma_driver = {
        },
 };
 
-bool omap_dma_filter_fn(struct dma_chan *chan, void *param)
+static bool omap_dma_filter_fn(struct dma_chan *chan, void *param)
 {
        if (chan->device->dev->driver == &omap_dma_driver.driver) {
                struct omap_dmadev *od = to_omap_dma_dev(chan->device);
@@ -1653,7 +1670,6 @@ bool omap_dma_filter_fn(struct dma_chan *chan, void *param)
        }
        return false;
 }
-EXPORT_SYMBOL_GPL(omap_dma_filter_fn);
 
 static int omap_dma_init(void)
 {