dmaengine: Add metadata_ops for dma_async_tx_descriptor
[rpmsg/hwspinlock.git] / include / linux / dmaengine.h
index d49ec5c31944863137f044b4046808dab60fe4ea..d33a953c9b55fcfe6ba9c4a0471fdabbc70051b2 100644 (file)
@@ -231,6 +231,58 @@ typedef struct { DECLARE_BITMAP(bits, DMA_TX_TYPE_END); } dma_cap_mask_t;
  * @bytes_transferred: byte counter
  */
 
+/**
+ * enum dma_desc_metadata_mode - per descriptor metadata mode types supported
+ * @DESC_METADATA_CLIENT - the metadata buffer is allocated/provided by the
+ *  client driver and it is attached (via the dmaengine_desc_attach_metadata()
+ *  helper) to the descriptor.
+ *
+ * Client drivers interested to use this mode can follow:
+ * - DMA_MEM_TO_DEV / DEV_MEM_TO_MEM:
+ *   1. prepare the descriptor (dmaengine_prep_*)
+ *     construct the metadata in the client's buffer
+ *   2. use dmaengine_desc_attach_metadata() to attach the buffer to the
+ *     descriptor
+ *   3. submit the transfer
+ * - DMA_DEV_TO_MEM:
+ *   1. prepare the descriptor (dmaengine_prep_*)
+ *   2. use dmaengine_desc_attach_metadata() to attach the buffer to the
+ *     descriptor
+ *   3. submit the transfer
+ *   4. when the transfer is completed, the metadata should be available in the
+ *     attached buffer
+ *
+ * @DESC_METADATA_ENGINE - the metadata buffer is allocated/managed by the DMA
+ *  driver. The client driver can ask for the pointer, maximum size and the
+ *  currently used size of the metadata and can directly update or read it.
+ *  dmaengine_desc_get_metadata_ptr() and dmaengine_desc_set_metadata_len() is
+ *  provided as helper functions.
+ *
+ * Client drivers interested to use this mode can follow:
+ * - DMA_MEM_TO_DEV / DEV_MEM_TO_MEM:
+ *   1. prepare the descriptor (dmaengine_prep_*)
+ *   2. use dmaengine_desc_get_metadata_ptr() to get the pointer to the engine's
+ *     metadata area
+ *   3. update the metadata at the pointer
+ *   4. use dmaengine_desc_set_metadata_len()  to tell the DMA engine the amount
+ *     of data the client has placed into the metadata buffer
+ *   5. submit the transfer
+ * - DMA_DEV_TO_MEM:
+ *   1. prepare the descriptor (dmaengine_prep_*)
+ *   2. submit the transfer
+ *   3. on transfer completion, use dmaengine_desc_get_metadata_ptr() to get the
+ *     pointer to the engine's metadata are
+ *   4. Read out the metadate from the pointer
+ *
+ * Note: the two mode is not compatible and clients must use one mode for a
+ * descriptor.
+ */
+enum dma_desc_metadata_mode {
+       DESC_METADATA_NONE = 0,
+       DESC_METADATA_CLIENT = BIT(0),
+       DESC_METADATA_ENGINE = BIT(1),
+};
+
 struct dma_chan_percpu {
        /* stats */
        unsigned long memcpy_count;
@@ -487,6 +539,18 @@ struct dmaengine_unmap_data {
        dma_addr_t addr[0];
 };
 
+struct dma_async_tx_descriptor;
+
+struct dma_descriptor_metadata_ops {
+       int (*attach)(struct dma_async_tx_descriptor *desc, void *data,
+                     size_t len);
+
+       void *(*get_ptr)(struct dma_async_tx_descriptor *desc,
+                        size_t *payload_len, size_t *max_len);
+       int (*set_len)(struct dma_async_tx_descriptor *desc,
+                      size_t payload_len);
+};
+
 /**
  * struct dma_async_tx_descriptor - async transaction descriptor
  * ---dma generic offload fields---
@@ -500,6 +564,11 @@ struct dmaengine_unmap_data {
  * descriptor pending. To be pushed on .issue_pending() call
  * @callback: routine to call after this operation is complete
  * @callback_param: general parameter to pass to the callback routine
+ * @desc_metadata_mode: core managed metadata mode to protect mixed use of
+ *     DESC_METADATA_CLIENT or DESC_METADATA_ENGINE. Otherwise
+ *     DESC_METADATA_NONE
+ * @metadata_ops: DMA driver provided metadata mode ops, need to be set by the
+ *     DMA driver if metadata mode is supported with the descriptor
  * ---async_tx api specific fields---
  * @next: at completion submit this descriptor
  * @parent: pointer to the next level up in the dependency chain
@@ -516,6 +585,8 @@ struct dma_async_tx_descriptor {
        dma_async_tx_callback_result callback_result;
        void *callback_param;
        struct dmaengine_unmap_data *unmap;
+       enum dma_desc_metadata_mode desc_metadata_mode;
+       struct dma_descriptor_metadata_ops *metadata_ops;
 #ifdef CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH
        struct dma_async_tx_descriptor *next;
        struct dma_async_tx_descriptor *parent;
@@ -678,6 +749,7 @@ struct dma_filter {
  * @global_node: list_head for global dma_device_list
  * @filter: information for device/slave to filter function/param mapping
  * @cap_mask: one or more dma_capability flags
+ * @desc_metadata_modes: supported metadata modes by the DMA device
  * @max_xor: maximum number of xor sources, 0 if no capability
  * @max_pq: maximum number of PQ sources and PQ-continue capability
  * @copy_align: alignment shift for memcpy operations
@@ -739,6 +811,7 @@ struct dma_device {
        struct list_head global_node;
        struct dma_filter filter;
        dma_cap_mask_t  cap_mask;
+       enum dma_desc_metadata_mode desc_metadata_modes;
        unsigned short max_xor;
        unsigned short max_pq;
        enum dmaengine_alignment copy_align;
@@ -914,6 +987,41 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_memcpy(
                                                    len, flags);
 }
 
+static inline bool dmaengine_is_metadata_mode_supported(struct dma_chan *chan,
+               enum dma_desc_metadata_mode mode)
+{
+       if (!chan)
+               return false;
+
+       return !!(chan->device->desc_metadata_modes & mode);
+}
+
+#ifdef CONFIG_DMA_ENGINE
+int dmaengine_desc_attach_metadata(struct dma_async_tx_descriptor *desc,
+                                  void *data, size_t len);
+void *dmaengine_desc_get_metadata_ptr(struct dma_async_tx_descriptor *desc,
+                                     size_t *payload_len, size_t *max_len);
+int dmaengine_desc_set_metadata_len(struct dma_async_tx_descriptor *desc,
+                                   size_t payload_len);
+#else /* CONFIG_DMA_ENGINE */
+static inline int dmaengine_desc_attach_metadata(
+               struct dma_async_tx_descriptor *desc, void *data, size_t len)
+{
+       return -EINVAL;
+}
+static inline void *dmaengine_desc_get_metadata_ptr(
+               struct dma_async_tx_descriptor *desc, size_t *payload_len,
+               size_t *max_len)
+{
+       return NULL;
+}
+static inline int dmaengine_desc_set_metadata_len(
+               struct dma_async_tx_descriptor *desc, size_t payload_len)
+{
+       return -EINVAL;
+}
+#endif /* CONFIG_DMA_ENGINE */
+
 /**
  * dmaengine_terminate_all() - Terminate all active DMA transfers
  * @chan: The channel for which to terminate the transfers