Merge tag 'mips-fixes_5.14_1' of git://git.kernel.org/pub/scm/linux/kernel/git/mips...
[linux-2.6-microblaze.git] / drivers / dma / xilinx / xilinx_dma.c
index 75c0b8e..4b9530a 100644 (file)
@@ -394,6 +394,7 @@ struct xilinx_dma_tx_descriptor {
  * @genlock: Support genlock mode
  * @err: Channel has errors
  * @idle: Check for channel idle
+ * @terminating: Check for channel being synchronized by user
  * @tasklet: Cleanup work after irq
  * @config: Device configuration info
  * @flush_on_fsync: Flush on Frame sync
@@ -431,6 +432,7 @@ struct xilinx_dma_chan {
        bool genlock;
        bool err;
        bool idle;
+       bool terminating;
        struct tasklet_struct tasklet;
        struct xilinx_vdma_config config;
        bool flush_on_fsync;
@@ -1049,6 +1051,13 @@ static void xilinx_dma_chan_desc_cleanup(struct xilinx_dma_chan *chan)
                /* Run any dependencies, then free the descriptor */
                dma_run_dependencies(&desc->async_tx);
                xilinx_dma_free_tx_descriptor(chan, desc);
+
+               /*
+                * While we ran a callback the user called a terminate function,
+                * which takes care of cleaning up any remaining descriptors
+                */
+               if (chan->terminating)
+                       break;
        }
 
        spin_unlock_irqrestore(&chan->lock, flags);
@@ -1965,6 +1974,8 @@ static dma_cookie_t xilinx_dma_tx_submit(struct dma_async_tx_descriptor *tx)
        if (desc->cyclic)
                chan->cyclic = true;
 
+       chan->terminating = false;
+
        spin_unlock_irqrestore(&chan->lock, flags);
 
        return cookie;
@@ -2436,6 +2447,7 @@ static int xilinx_dma_terminate_all(struct dma_chan *dchan)
 
        xilinx_dma_chan_reset(chan);
        /* Remove and free all of the descriptors in the lists */
+       chan->terminating = true;
        xilinx_dma_free_descriptors(chan);
        chan->idle = true;