From: Gustavo Pimentel <Gustavo.Pimentel@synopsys.com> To: dmaengine@vger.kernel.org, linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, Vinod Koul <vkoul@kernel.org>, Dan Williams <dan.j.williams@intel.com>, Bjorn Helgaas <bhelgaas@google.com>, Gustavo Pimentel <Gustavo.Pimentel@synopsys.com> Subject: [PATCH v5 06/15] dmaengine: dw-edma: Add device_prep_interleave_dma() support Date: Thu, 11 Feb 2021 10:12:39 +0100 [thread overview] Message-ID: <bd6df859545aba8fa5de14cc19792dde070b0950.1613034728.git.gustavo.pimentel@synopsys.com> (raw) In-Reply-To: <cover.1613034728.git.gustavo.pimentel@synopsys.com> In-Reply-To: <cover.1613034728.git.gustavo.pimentel@synopsys.com> Add device_prep_interleave_dma() support to Synopsys DMA driver. This feature implements a similar data transfer mechanism to the scatter-gather implementation. Signed-off-by: Gustavo Pimentel <gustavo.pimentel@synopsys.com> --- drivers/dma/dw-edma/dw-edma-core.c | 85 ++++++++++++++++++++++++++++++-------- drivers/dma/dw-edma/dw-edma-core.h | 13 ++++-- 2 files changed, 78 insertions(+), 20 deletions(-) diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c index b65c32e1..0fe3835 100644 --- a/drivers/dma/dw-edma/dw-edma-core.c +++ b/drivers/dma/dw-edma/dw-edma-core.c @@ -329,7 +329,7 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer) struct dw_edma_chunk *chunk; struct dw_edma_burst *burst; struct dw_edma_desc *desc; - u32 cnt; + u32 cnt = 0; int i; if (!chan->configured) @@ -352,12 +352,19 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer) return NULL; } - if (xfer->cyclic) { + if (xfer->type == EDMA_XFER_CYCLIC) { if (!xfer->xfer.cyclic.len || !xfer->xfer.cyclic.cnt) return NULL; - } else { + } else if (xfer->type == EDMA_XFER_SCATTER_GATHER) { if (xfer->xfer.sg.len < 1) return NULL; + } else if (xfer->type == EDMA_XFER_INTERLEAVED) { + if (!xfer->xfer.il->numf) + return NULL; + if (xfer->xfer.il->numf > 0 && xfer->xfer.il->frame_size > 0) + return NULL; + } else { + return NULL; } desc = dw_edma_alloc_desc(chan); @@ -368,18 +375,28 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer) if (unlikely(!chunk)) goto err_alloc; - src_addr = chan->config.src_addr; - dst_addr = chan->config.dst_addr; + if (xfer->type == EDMA_XFER_INTERLEAVED) { + src_addr = xfer->xfer.il->src_start; + dst_addr = xfer->xfer.il->dst_start; + } else { + src_addr = chan->config.src_addr; + dst_addr = chan->config.dst_addr; + } - if (xfer->cyclic) { + if (xfer->type == EDMA_XFER_CYCLIC) { cnt = xfer->xfer.cyclic.cnt; - } else { + } else if (xfer->type == EDMA_XFER_SCATTER_GATHER) { cnt = xfer->xfer.sg.len; sg = xfer->xfer.sg.sgl; + } else if (xfer->type == EDMA_XFER_INTERLEAVED) { + if (xfer->xfer.il->numf > 0) + cnt = xfer->xfer.il->numf; + else + cnt = xfer->xfer.il->frame_size; } for (i = 0; i < cnt; i++) { - if (!xfer->cyclic && !sg) + if (xfer->type == EDMA_XFER_SCATTER_GATHER && !sg) break; if (chunk->bursts_alloc == chan->ll_max) { @@ -392,19 +409,21 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer) if (unlikely(!burst)) goto err_alloc; - if (xfer->cyclic) + if (xfer->type == EDMA_XFER_CYCLIC) burst->sz = xfer->xfer.cyclic.len; - else + else if (xfer->type == EDMA_XFER_SCATTER_GATHER) burst->sz = sg_dma_len(sg); + else if (xfer->type == EDMA_XFER_INTERLEAVED) + burst->sz = xfer->xfer.il->sgl[i].size; chunk->ll_region.sz += burst->sz; desc->alloc_sz += burst->sz; if (chan->dir == EDMA_DIR_WRITE) { burst->sar = src_addr; - if (xfer->cyclic) { + if (xfer->type == EDMA_XFER_CYCLIC) { burst->dar = xfer->xfer.cyclic.paddr; - } else { + } else if (xfer->type == EDMA_XFER_SCATTER_GATHER) { burst->dar = dst_addr; /* Unlike the typical assumption by other * drivers/IPs the peripheral memory isn't @@ -416,9 +435,9 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer) } } else { burst->dar = dst_addr; - if (xfer->cyclic) { + if (xfer->type == EDMA_XFER_CYCLIC) { burst->sar = xfer->xfer.cyclic.paddr; - } else { + } else if (xfer->type == EDMA_XFER_SCATTER_GATHER) { burst->sar = src_addr; /* Unlike the typical assumption by other * drivers/IPs the peripheral memory isn't @@ -430,10 +449,24 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer) } } - if (!xfer->cyclic) { + if (xfer->type == EDMA_XFER_SCATTER_GATHER) { src_addr += sg_dma_len(sg); dst_addr += sg_dma_len(sg); sg = sg_next(sg); + } else if (xfer->type == EDMA_XFER_INTERLEAVED && + xfer->xfer.il->frame_size > 0) { + struct dma_interleaved_template *il = xfer->xfer.il; + struct data_chunk *dc = &il->sgl[i]; + + if (il->src_sgl) { + src_addr += burst->sz; + src_addr += dmaengine_get_src_icg(il, dc); + } + + if (il->dst_sgl) { + dst_addr += burst->sz; + dst_addr += dmaengine_get_dst_icg(il, dc); + } } } @@ -459,7 +492,7 @@ dw_edma_device_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl, xfer.xfer.sg.sgl = sgl; xfer.xfer.sg.len = len; xfer.flags = flags; - xfer.cyclic = false; + xfer.type = EDMA_XFER_SCATTER_GATHER; return dw_edma_device_transfer(&xfer); } @@ -478,7 +511,23 @@ dw_edma_device_prep_dma_cyclic(struct dma_chan *dchan, dma_addr_t paddr, xfer.xfer.cyclic.len = len; xfer.xfer.cyclic.cnt = count; xfer.flags = flags; - xfer.cyclic = true; + xfer.type = EDMA_XFER_CYCLIC; + + return dw_edma_device_transfer(&xfer); +} + +static struct dma_async_tx_descriptor * +dw_edma_device_prep_interleaved_dma(struct dma_chan *dchan, + struct dma_interleaved_template *ilt, + unsigned long flags) +{ + struct dw_edma_transfer xfer; + + xfer.dchan = dchan; + xfer.direction = ilt->dir; + xfer.xfer.il = ilt; + xfer.flags = flags; + xfer.type = EDMA_XFER_INTERLEAVED; return dw_edma_device_transfer(&xfer); } @@ -738,6 +787,7 @@ static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write, dma_cap_set(DMA_SLAVE, dma->cap_mask); dma_cap_set(DMA_CYCLIC, dma->cap_mask); dma_cap_set(DMA_PRIVATE, dma->cap_mask); + dma_cap_set(DMA_INTERLEAVE, dma->cap_mask); dma->directions = BIT(write ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV); dma->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); dma->dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); @@ -756,6 +806,7 @@ static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write, dma->device_tx_status = dw_edma_device_tx_status; dma->device_prep_slave_sg = dw_edma_device_prep_slave_sg; dma->device_prep_dma_cyclic = dw_edma_device_prep_dma_cyclic; + dma->device_prep_interleaved_dma = dw_edma_device_prep_interleaved_dma; dma_set_max_seg_size(dma->dev, U32_MAX); diff --git a/drivers/dma/dw-edma/dw-edma-core.h b/drivers/dma/dw-edma/dw-edma-core.h index 3f9593e..f72ebaa 100644 --- a/drivers/dma/dw-edma/dw-edma-core.h +++ b/drivers/dma/dw-edma/dw-edma-core.h @@ -39,6 +39,12 @@ enum dw_edma_status { EDMA_ST_BUSY }; +enum dw_edma_xfer_type { + EDMA_XFER_SCATTER_GATHER = 0, + EDMA_XFER_CYCLIC, + EDMA_XFER_INTERLEAVED +}; + struct dw_edma_chan; struct dw_edma_chunk; @@ -146,12 +152,13 @@ struct dw_edma_cyclic { struct dw_edma_transfer { struct dma_chan *dchan; union dw_edma_xfer { - struct dw_edma_sg sg; - struct dw_edma_cyclic cyclic; + struct dw_edma_sg sg; + struct dw_edma_cyclic cyclic; + struct dma_interleaved_template *il; } xfer; enum dma_transfer_direction direction; unsigned long flags; - bool cyclic; + enum dw_edma_xfer_type type; }; static inline -- 2.7.4
next prev parent reply other threads:[~2021-02-11 9:18 UTC|newest] Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top 2021-02-11 9:12 [PATCH v5 00/15] dmaengine: dw-edma: HDMA support Gustavo Pimentel 2021-02-11 9:12 ` [PATCH v5 01/15] dmaengine: dw-edma: Add writeq() and readq() for 64 bits architectures Gustavo Pimentel 2021-02-11 9:12 ` [PATCH v5 02/15] dmaengine: dw-edma: Fix comments offset characters' alignment Gustavo Pimentel 2021-02-11 9:12 ` [PATCH v5 03/15] dmaengine: dw-edma: Add support for the HDMA feature Gustavo Pimentel 2021-02-11 9:12 ` [PATCH v5 04/15] PCI: Add pci_find_vsec_capability() to find a specific VSEC Gustavo Pimentel 2021-02-11 12:50 ` Krzysztof Wilczyński 2021-02-11 19:42 ` Gustavo Pimentel 2021-02-11 9:12 ` [PATCH v5 05/15] dmaengine: dw-edma: Add PCIe VSEC data retrieval support Gustavo Pimentel 2021-02-11 12:59 ` Krzysztof Wilczyński 2021-02-11 13:48 ` Gustavo Pimentel 2021-02-11 9:12 ` Gustavo Pimentel [this message] 2021-02-11 9:12 ` [PATCH v5 07/15] dmaengine: dw-edma: Improve number of channels check Gustavo Pimentel 2021-02-11 9:12 ` [PATCH v5 08/15] dmaengine: dw-edma: Reorder variables to keep consistency Gustavo Pimentel 2021-02-11 9:12 ` [PATCH v5 09/15] dmaengine: dw-edma: Improve the linked list and data blocks definition Gustavo Pimentel 2021-02-11 13:08 ` Krzysztof Wilczyński 2021-02-11 9:12 ` [PATCH v5 10/15] dmaengine: dw-edma: Change linked list and data blocks offset and sizes Gustavo Pimentel 2021-02-11 9:12 ` [PATCH v5 11/15] dmaengine: dw-edma: Move struct dentry variable from static definition into dw_edma struct Gustavo Pimentel 2021-02-11 9:12 ` [PATCH v5 12/15] dmaengine: dw-edma: Fix crash on loading/unloading driver Gustavo Pimentel 2021-02-11 9:12 ` [PATCH v5 13/15] dmaengine: dw-edma: Change DMA abreviation from lower into upper case Gustavo Pimentel 2021-02-11 9:12 ` [PATCH v5 14/15] dmaengine: dw-edma: Revert fix scatter-gather address calculation Gustavo Pimentel 2021-02-11 13:09 ` Krzysztof Wilczyński 2021-02-11 9:12 ` [PATCH v5 15/15] dmaengine: dw-edma: Add pcim_iomap_table return check Gustavo Pimentel 2021-02-11 13:14 ` Krzysztof Wilczyński
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=bd6df859545aba8fa5de14cc19792dde070b0950.1613034728.git.gustavo.pimentel@synopsys.com \ --to=gustavo.pimentel@synopsys.com \ --cc=bhelgaas@google.com \ --cc=dan.j.williams@intel.com \ --cc=dmaengine@vger.kernel.org \ --cc=linux-kernel@vger.kernel.org \ --cc=linux-pci@vger.kernel.org \ --cc=vkoul@kernel.org \ --subject='Re: [PATCH v5 06/15] dmaengine: dw-edma: Add device_prep_interleave_dma() support' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).