dmaengine: Add DMA_CTRL_REUSE
authorVinod Koul <vinod.koul@intel.com>
Wed, 5 Aug 2015 03:12:05 +0000 (08:42 +0530)
committerVinod Koul <vinod.koul@intel.com>
Mon, 17 Aug 2015 09:22:02 +0000 (14:52 +0530)
This adds new descriptor flag for reusing a descriptor by submitting
multiple times by a client, for example video buffer.
Add helper APIs for this as well

Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Acked-by:Robert Jarzmik <robert.jarzmik@free.fr>

include/linux/dmaengine.h

index 8ad9a4e..1b866e9 100644 (file)
@@ -184,6 +184,8 @@ struct dma_interleaved_template {
  *  operation it continues the calculation with new sources
  * @DMA_PREP_FENCE - tell the driver that subsequent operations depend
  *  on the result of this operation
+ * @DMA_CTRL_REUSE: client can reuse the descriptor and submit again till
+ *  cleared or freed
  */
 enum dma_ctrl_flags {
        DMA_PREP_INTERRUPT = (1 << 0),
@@ -192,6 +194,7 @@ enum dma_ctrl_flags {
        DMA_PREP_PQ_DISABLE_Q = (1 << 3),
        DMA_PREP_CONTINUE = (1 << 4),
        DMA_PREP_FENCE = (1 << 5),
+       DMA_CTRL_REUSE = (1 << 6),
 };
 
 /**
@@ -401,6 +404,8 @@ enum dma_residue_granularity {
  * @cmd_pause: true, if pause and thereby resume is supported
  * @cmd_terminate: true, if terminate cmd is supported
  * @residue_granularity: granularity of the reported transfer residue
+ * @descriptor_reuse: if a descriptor can be reused by client and
+ * resubmitted multiple times
  */
 struct dma_slave_caps {
        u32 src_addr_widths;
@@ -409,6 +414,7 @@ struct dma_slave_caps {
        bool cmd_pause;
        bool cmd_terminate;
        enum dma_residue_granularity residue_granularity;
+       bool descriptor_reuse;
 };
 
 static inline const char *dma_chan_name(struct dma_chan *chan)
@@ -468,6 +474,7 @@ struct dma_async_tx_descriptor {
        dma_addr_t phys;
        struct dma_chan *chan;
        dma_cookie_t (*tx_submit)(struct dma_async_tx_descriptor *tx);
+       int (*desc_free)(struct dma_async_tx_descriptor *tx);
        dma_async_tx_callback callback;
        void *callback_param;
        struct dmaengine_unmap_data *unmap;
@@ -1175,6 +1182,39 @@ static inline int dma_get_slave_caps(struct dma_chan *chan,
 }
 #endif
 
+static inline int dmaengine_desc_set_reuse(struct dma_async_tx_descriptor *tx)
+{
+       struct dma_slave_caps caps;
+
+       dma_get_slave_caps(tx->chan, &caps);
+
+       if (caps.descriptor_reuse) {
+               tx->flags |= DMA_CTRL_REUSE;
+               return 0;
+       } else {
+               return -EPERM;
+       }
+}
+
+static inline void dmaengine_desc_clear_reuse(struct dma_async_tx_descriptor *tx)
+{
+       tx->flags &= ~DMA_CTRL_REUSE;
+}
+
+static inline bool dmaengine_desc_test_reuse(struct dma_async_tx_descriptor *tx)
+{
+       return (tx->flags & DMA_CTRL_REUSE) == DMA_CTRL_REUSE;
+}
+
+static inline int dmaengine_desc_free(struct dma_async_tx_descriptor *desc)
+{
+       /* this is supported for reusable desc, so check that */
+       if (dmaengine_desc_test_reuse(desc))
+               return desc->desc_free(desc);
+       else
+               return -EPERM;
+}
+
 /* --- DMA device --- */
 
 int dma_async_device_register(struct dma_device *device);