dmaengine: Add core function and capability check for DMA_MEMCPY_SG
authorAdrian Larumbe <adrianml@alumnos.upm.es>
Mon, 1 Nov 2021 18:08:24 +0000 (18:08 +0000)
committerVinod Koul <vkoul@kernel.org>
Mon, 22 Nov 2021 06:08:05 +0000 (11:38 +0530)
This is the old DMA_SG interface that was removed in commit
c678fa66341c ("dmaengine: remove DMA_SG as it is dead code in kernel"). It
has been renamed to DMA_MEMCPY_SG to better match the MEMSET and MEMSET_SG
naming convention.

It should only be used for mem2mem copies, either main system memory or
CPU-addressable device memory (like video memory on a PCI graphics card).

Bringing back this interface was prompted by the need to use the Xilinx
CDMA device for mem2mem SG transfers.

Signed-off-by: Adrian Larumbe <adrianml@alumnos.upm.es>
Link: https://lore.kernel.org/r/20211101180825.241048-3-adrianml@alumnos.upm.es
Signed-off-by: Vinod Koul <vkoul@kernel.org>
drivers/dma/dmaengine.c
include/linux/dmaengine.h

index d9f7c09..2cfa845 100644 (file)
@@ -1159,6 +1159,13 @@ int dma_async_device_register(struct dma_device *device)
                return -EIO;
        }
 
+       if (dma_has_cap(DMA_MEMCPY_SG, device->cap_mask) && !device->device_prep_dma_memcpy_sg) {
+               dev_err(device->dev,
+                       "Device claims capability %s, but op is not defined\n",
+                       "DMA_MEMCPY_SG");
+               return -EIO;
+       }
+
        if (dma_has_cap(DMA_XOR, device->cap_mask) && !device->device_prep_dma_xor) {
                dev_err(device->dev,
                        "Device claims capability %s, but op is not defined\n",
index 9000f3f..554a866 100644 (file)
@@ -50,6 +50,7 @@ enum dma_status {
  */
 enum dma_transaction_type {
        DMA_MEMCPY,
+       DMA_MEMCPY_SG,
        DMA_XOR,
        DMA_PQ,
        DMA_XOR_VAL,
@@ -891,6 +892,11 @@ struct dma_device {
        struct dma_async_tx_descriptor *(*device_prep_dma_memcpy)(
                struct dma_chan *chan, dma_addr_t dst, dma_addr_t src,
                size_t len, unsigned long flags);
+       struct dma_async_tx_descriptor *(*device_prep_dma_memcpy_sg)(
+               struct dma_chan *chan,
+               struct scatterlist *dst_sg, unsigned int dst_nents,
+               struct scatterlist *src_sg, unsigned int src_nents,
+               unsigned long flags);
        struct dma_async_tx_descriptor *(*device_prep_dma_xor)(
                struct dma_chan *chan, dma_addr_t dst, dma_addr_t *src,
                unsigned int src_cnt, size_t len, unsigned long flags);
@@ -1051,6 +1057,20 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_memcpy(
                                                    len, flags);
 }
 
+static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_memcpy_sg(
+               struct dma_chan *chan,
+               struct scatterlist *dst_sg, unsigned int dst_nents,
+               struct scatterlist *src_sg, unsigned int src_nents,
+               unsigned long flags)
+{
+       if (!chan || !chan->device || !chan->device->device_prep_dma_memcpy_sg)
+               return NULL;
+
+       return chan->device->device_prep_dma_memcpy_sg(chan, dst_sg, dst_nents,
+                                                      src_sg, src_nents,
+                                                      flags);
+}
+
 static inline bool dmaengine_is_metadata_mode_supported(struct dma_chan *chan,
                enum dma_desc_metadata_mode mode)
 {