* [PATCH 0/2] dmaengine: hdmac: Add scatter-gathered memset support @ 2015-10-01 14:52 ` Maxime Ripard 0 siblings, 0 replies; 12+ messages in thread From: Maxime Ripard @ 2015-10-01 14:52 UTC (permalink / raw) To: linux-arm-kernel Hi Vinod, Here is a patch serie that adds support in the Atmel HDMAC for memset over a discontiguous memory area. Just like for the memset, it's used on those SoCs to support framebuffer related operations that cannot be performed either by the display engine or the (non-existent) GPU. Let me know what you think, Maxime Maxime Ripard (2): dmaengine: hdmac: factorise memset descriptor allocation dmaengine: hdmac: Add scatter-gathered memset support drivers/dma/at_hdmac.c | 169 ++++++++++++++++++++++++++++++++++---------- drivers/dma/at_hdmac_regs.h | 2 +- 2 files changed, 134 insertions(+), 37 deletions(-) -- 2.5.3 ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 0/2] dmaengine: hdmac: Add scatter-gathered memset support @ 2015-10-01 14:52 ` Maxime Ripard 0 siblings, 0 replies; 12+ messages in thread From: Maxime Ripard @ 2015-10-01 14:52 UTC (permalink / raw) To: Vinod Koul, Nicolas Ferre, Alexandre Belloni Cc: dmaengine, linux-kernel, linux-arm-kernel, Ludovic Desroches, Cyrille Pitchen, Maxime Ripard Hi Vinod, Here is a patch serie that adds support in the Atmel HDMAC for memset over a discontiguous memory area. Just like for the memset, it's used on those SoCs to support framebuffer related operations that cannot be performed either by the display engine or the (non-existent) GPU. Let me know what you think, Maxime Maxime Ripard (2): dmaengine: hdmac: factorise memset descriptor allocation dmaengine: hdmac: Add scatter-gathered memset support drivers/dma/at_hdmac.c | 169 ++++++++++++++++++++++++++++++++++---------- drivers/dma/at_hdmac_regs.h | 2 +- 2 files changed, 134 insertions(+), 37 deletions(-) -- 2.5.3 ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/2] dmaengine: hdmac: factorise memset descriptor allocation 2015-10-01 14:52 ` Maxime Ripard @ 2015-10-01 14:52 ` Maxime Ripard -1 siblings, 0 replies; 12+ messages in thread From: Maxime Ripard @ 2015-10-01 14:52 UTC (permalink / raw) To: linux-arm-kernel The memset and scatter gathered memset are going to use some common logic to create their descriptors. Move that logic into a function of its own so that we can share it with the future memset_sg callback. Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> --- drivers/dma/at_hdmac.c | 98 +++++++++++++++++++++++++++------------------ drivers/dma/at_hdmac_regs.h | 2 +- 2 files changed, 59 insertions(+), 41 deletions(-) diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 58d406230d89..009103fd6d9a 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -458,10 +458,10 @@ atc_chain_complete(struct at_dma_chan *atchan, struct at_desc *desc) dma_cookie_complete(txd); /* If the transfer was a memset, free our temporary buffer */ - if (desc->memset) { + if (desc->memset_buffer) { dma_pool_free(atdma->memset_pool, desc->memset_vaddr, desc->memset_paddr); - desc->memset = false; + desc->memset_buffer = false; } /* move children to free_list */ @@ -881,6 +881,47 @@ err_desc_get: return NULL; } +static struct at_desc *atc_create_memset_desc(struct dma_chan *chan, + dma_addr_t psrc, + dma_addr_t pdst, + size_t len) +{ + struct at_dma_chan *atchan = to_at_dma_chan(chan); + struct at_desc *desc; + size_t xfer_count; + + u32 ctrla = ATC_SRC_WIDTH(2) | + ATC_DST_WIDTH(2); + u32 ctrlb = ATC_DEFAULT_CTRLB | ATC_IEN | + ATC_SRC_ADDR_MODE_FIXED | + ATC_DST_ADDR_MODE_INCR | + ATC_FC_MEM2MEM; + + xfer_count = len >> 2; + if (xfer_count > ATC_BTSIZE_MAX) { + dev_err(chan2dev(chan), "%s: buffer is too big\n", + __func__); + return NULL; + } + + desc = atc_desc_get(atchan); + if (!desc) { + dev_err(chan2dev(chan), "%s: can't get a descriptor\n", + __func__); + return NULL; + } + + desc->lli.saddr = psrc; + desc->lli.daddr = pdst; + desc->lli.ctrla = ctrla | xfer_count; + desc->lli.ctrlb = ctrlb; + + desc->txd.cookie = 0; + desc->len = len; + + return desc; +} + /** * atc_prep_dma_memset - prepare a memcpy operation * @chan: the channel to prepare operation on @@ -893,12 +934,10 @@ static struct dma_async_tx_descriptor * atc_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value, size_t len, unsigned long flags) { - struct at_dma_chan *atchan = to_at_dma_chan(chan); struct at_dma *atdma = to_at_dma(chan->device); - struct at_desc *desc = NULL; - size_t xfer_count; - u32 ctrla; - u32 ctrlb; + struct at_desc *desc; + void __iomem *vaddr; + dma_addr_t paddr; dev_vdbg(chan2dev(chan), "%s: d0x%x v0x%x l0x%zx f0x%lx\n", __func__, dest, value, len, flags); @@ -914,46 +953,26 @@ atc_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value, return NULL; } - xfer_count = len >> 2; - if (xfer_count > ATC_BTSIZE_MAX) { - dev_err(chan2dev(chan), "%s: buffer is too big\n", + vaddr = dma_pool_alloc(atdma->memset_pool, GFP_ATOMIC, &paddr); + if (!vaddr) { + dev_err(chan2dev(chan), "%s: couldn't allocate buffer\n", __func__); return NULL; } + *(u32*)vaddr = value; - ctrlb = ATC_DEFAULT_CTRLB | ATC_IEN - | ATC_SRC_ADDR_MODE_FIXED - | ATC_DST_ADDR_MODE_INCR - | ATC_FC_MEM2MEM; - - ctrla = ATC_SRC_WIDTH(2) | - ATC_DST_WIDTH(2); - - desc = atc_desc_get(atchan); + desc = atc_create_memset_desc(chan, paddr, dest, len); if (!desc) { - dev_err(chan2dev(chan), "%s: can't get a descriptor\n", + dev_err(chan2dev(chan), "%s: couldn't get a descriptor\n", __func__); - return NULL; + goto err_free_buffer; } - desc->memset_vaddr = dma_pool_alloc(atdma->memset_pool, GFP_ATOMIC, - &desc->memset_paddr); - if (!desc->memset_vaddr) { - dev_err(chan2dev(chan), "%s: couldn't allocate buffer\n", - __func__); - goto err_put_desc; - } - - *desc->memset_vaddr = value; - desc->memset = true; - - desc->lli.saddr = desc->memset_paddr; - desc->lli.daddr = dest; - desc->lli.ctrla = ctrla | xfer_count; - desc->lli.ctrlb = ctrlb; + desc->memset_paddr = paddr; + desc->memset_vaddr = vaddr; + desc->memset_buffer = true; desc->txd.cookie = -EBUSY; - desc->len = len; desc->total_len = len; /* set end-of-link on the descriptor */ @@ -963,12 +982,11 @@ atc_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value, return &desc->txd; -err_put_desc: - atc_desc_put(atchan, desc); +err_free_buffer: + dma_pool_free(atdma->memset_pool, vaddr, paddr); return NULL; } - /** * atc_prep_slave_sg - prepare descriptors for a DMA_SLAVE transaction * @chan: DMA channel diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h index c3bebbe899ac..d1cfc8c876f9 100644 --- a/drivers/dma/at_hdmac_regs.h +++ b/drivers/dma/at_hdmac_regs.h @@ -202,7 +202,7 @@ struct at_desc { size_t src_hole; /* Memset temporary buffer */ - bool memset; + bool memset_buffer; dma_addr_t memset_paddr; int *memset_vaddr; }; -- 2.5.3 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 1/2] dmaengine: hdmac: factorise memset descriptor allocation @ 2015-10-01 14:52 ` Maxime Ripard 0 siblings, 0 replies; 12+ messages in thread From: Maxime Ripard @ 2015-10-01 14:52 UTC (permalink / raw) To: Vinod Koul, Nicolas Ferre, Alexandre Belloni Cc: dmaengine, linux-kernel, linux-arm-kernel, Ludovic Desroches, Cyrille Pitchen, Maxime Ripard The memset and scatter gathered memset are going to use some common logic to create their descriptors. Move that logic into a function of its own so that we can share it with the future memset_sg callback. Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> --- drivers/dma/at_hdmac.c | 98 +++++++++++++++++++++++++++------------------ drivers/dma/at_hdmac_regs.h | 2 +- 2 files changed, 59 insertions(+), 41 deletions(-) diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 58d406230d89..009103fd6d9a 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -458,10 +458,10 @@ atc_chain_complete(struct at_dma_chan *atchan, struct at_desc *desc) dma_cookie_complete(txd); /* If the transfer was a memset, free our temporary buffer */ - if (desc->memset) { + if (desc->memset_buffer) { dma_pool_free(atdma->memset_pool, desc->memset_vaddr, desc->memset_paddr); - desc->memset = false; + desc->memset_buffer = false; } /* move children to free_list */ @@ -881,6 +881,47 @@ err_desc_get: return NULL; } +static struct at_desc *atc_create_memset_desc(struct dma_chan *chan, + dma_addr_t psrc, + dma_addr_t pdst, + size_t len) +{ + struct at_dma_chan *atchan = to_at_dma_chan(chan); + struct at_desc *desc; + size_t xfer_count; + + u32 ctrla = ATC_SRC_WIDTH(2) | + ATC_DST_WIDTH(2); + u32 ctrlb = ATC_DEFAULT_CTRLB | ATC_IEN | + ATC_SRC_ADDR_MODE_FIXED | + ATC_DST_ADDR_MODE_INCR | + ATC_FC_MEM2MEM; + + xfer_count = len >> 2; + if (xfer_count > ATC_BTSIZE_MAX) { + dev_err(chan2dev(chan), "%s: buffer is too big\n", + __func__); + return NULL; + } + + desc = atc_desc_get(atchan); + if (!desc) { + dev_err(chan2dev(chan), "%s: can't get a descriptor\n", + __func__); + return NULL; + } + + desc->lli.saddr = psrc; + desc->lli.daddr = pdst; + desc->lli.ctrla = ctrla | xfer_count; + desc->lli.ctrlb = ctrlb; + + desc->txd.cookie = 0; + desc->len = len; + + return desc; +} + /** * atc_prep_dma_memset - prepare a memcpy operation * @chan: the channel to prepare operation on @@ -893,12 +934,10 @@ static struct dma_async_tx_descriptor * atc_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value, size_t len, unsigned long flags) { - struct at_dma_chan *atchan = to_at_dma_chan(chan); struct at_dma *atdma = to_at_dma(chan->device); - struct at_desc *desc = NULL; - size_t xfer_count; - u32 ctrla; - u32 ctrlb; + struct at_desc *desc; + void __iomem *vaddr; + dma_addr_t paddr; dev_vdbg(chan2dev(chan), "%s: d0x%x v0x%x l0x%zx f0x%lx\n", __func__, dest, value, len, flags); @@ -914,46 +953,26 @@ atc_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value, return NULL; } - xfer_count = len >> 2; - if (xfer_count > ATC_BTSIZE_MAX) { - dev_err(chan2dev(chan), "%s: buffer is too big\n", + vaddr = dma_pool_alloc(atdma->memset_pool, GFP_ATOMIC, &paddr); + if (!vaddr) { + dev_err(chan2dev(chan), "%s: couldn't allocate buffer\n", __func__); return NULL; } + *(u32*)vaddr = value; - ctrlb = ATC_DEFAULT_CTRLB | ATC_IEN - | ATC_SRC_ADDR_MODE_FIXED - | ATC_DST_ADDR_MODE_INCR - | ATC_FC_MEM2MEM; - - ctrla = ATC_SRC_WIDTH(2) | - ATC_DST_WIDTH(2); - - desc = atc_desc_get(atchan); + desc = atc_create_memset_desc(chan, paddr, dest, len); if (!desc) { - dev_err(chan2dev(chan), "%s: can't get a descriptor\n", + dev_err(chan2dev(chan), "%s: couldn't get a descriptor\n", __func__); - return NULL; + goto err_free_buffer; } - desc->memset_vaddr = dma_pool_alloc(atdma->memset_pool, GFP_ATOMIC, - &desc->memset_paddr); - if (!desc->memset_vaddr) { - dev_err(chan2dev(chan), "%s: couldn't allocate buffer\n", - __func__); - goto err_put_desc; - } - - *desc->memset_vaddr = value; - desc->memset = true; - - desc->lli.saddr = desc->memset_paddr; - desc->lli.daddr = dest; - desc->lli.ctrla = ctrla | xfer_count; - desc->lli.ctrlb = ctrlb; + desc->memset_paddr = paddr; + desc->memset_vaddr = vaddr; + desc->memset_buffer = true; desc->txd.cookie = -EBUSY; - desc->len = len; desc->total_len = len; /* set end-of-link on the descriptor */ @@ -963,12 +982,11 @@ atc_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value, return &desc->txd; -err_put_desc: - atc_desc_put(atchan, desc); +err_free_buffer: + dma_pool_free(atdma->memset_pool, vaddr, paddr); return NULL; } - /** * atc_prep_slave_sg - prepare descriptors for a DMA_SLAVE transaction * @chan: DMA channel diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h index c3bebbe899ac..d1cfc8c876f9 100644 --- a/drivers/dma/at_hdmac_regs.h +++ b/drivers/dma/at_hdmac_regs.h @@ -202,7 +202,7 @@ struct at_desc { size_t src_hole; /* Memset temporary buffer */ - bool memset; + bool memset_buffer; dma_addr_t memset_paddr; int *memset_vaddr; }; -- 2.5.3 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 1/2] dmaengine: hdmac: factorise memset descriptor allocation 2015-10-01 14:52 ` Maxime Ripard @ 2015-10-07 13:54 ` Vinod Koul -1 siblings, 0 replies; 12+ messages in thread From: Vinod Koul @ 2015-10-07 13:54 UTC (permalink / raw) To: linux-arm-kernel On Thu, Oct 01, 2015 at 04:52:37PM +0200, Maxime Ripard wrote: > +static struct at_desc *atc_create_memset_desc(struct dma_chan *chan, > + dma_addr_t psrc, > + dma_addr_t pdst, > + size_t len) > +{ > + struct at_dma_chan *atchan = to_at_dma_chan(chan); > + struct at_desc *desc; > + size_t xfer_count; > + > + u32 ctrla = ATC_SRC_WIDTH(2) | > + ATC_DST_WIDTH(2); why is this over two lines :) > + u32 ctrlb = ATC_DEFAULT_CTRLB | ATC_IEN | > + ATC_SRC_ADDR_MODE_FIXED | > + ATC_DST_ADDR_MODE_INCR | > + ATC_FC_MEM2MEM; > + > + xfer_count = len >> 2; > + if (xfer_count > ATC_BTSIZE_MAX) { > + dev_err(chan2dev(chan), "%s: buffer is too big\n", > + __func__); > + return NULL; > + } This is fine, but this is driver limitation. We should really split the txn to multiple descriptors here.. > @@ -914,46 +953,26 @@ atc_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value, > return NULL; > } > > - xfer_count = len >> 2; > - if (xfer_count > ATC_BTSIZE_MAX) { > - dev_err(chan2dev(chan), "%s: buffer is too big\n", > + vaddr = dma_pool_alloc(atdma->memset_pool, GFP_ATOMIC, &paddr); Mostly people use _zalloc variant, any reason why you don't want that -- ~Vinod ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/2] dmaengine: hdmac: factorise memset descriptor allocation @ 2015-10-07 13:54 ` Vinod Koul 0 siblings, 0 replies; 12+ messages in thread From: Vinod Koul @ 2015-10-07 13:54 UTC (permalink / raw) To: Maxime Ripard Cc: Nicolas Ferre, Alexandre Belloni, dmaengine, linux-kernel, linux-arm-kernel, Ludovic Desroches, Cyrille Pitchen On Thu, Oct 01, 2015 at 04:52:37PM +0200, Maxime Ripard wrote: > +static struct at_desc *atc_create_memset_desc(struct dma_chan *chan, > + dma_addr_t psrc, > + dma_addr_t pdst, > + size_t len) > +{ > + struct at_dma_chan *atchan = to_at_dma_chan(chan); > + struct at_desc *desc; > + size_t xfer_count; > + > + u32 ctrla = ATC_SRC_WIDTH(2) | > + ATC_DST_WIDTH(2); why is this over two lines :) > + u32 ctrlb = ATC_DEFAULT_CTRLB | ATC_IEN | > + ATC_SRC_ADDR_MODE_FIXED | > + ATC_DST_ADDR_MODE_INCR | > + ATC_FC_MEM2MEM; > + > + xfer_count = len >> 2; > + if (xfer_count > ATC_BTSIZE_MAX) { > + dev_err(chan2dev(chan), "%s: buffer is too big\n", > + __func__); > + return NULL; > + } This is fine, but this is driver limitation. We should really split the txn to multiple descriptors here.. > @@ -914,46 +953,26 @@ atc_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value, > return NULL; > } > > - xfer_count = len >> 2; > - if (xfer_count > ATC_BTSIZE_MAX) { > - dev_err(chan2dev(chan), "%s: buffer is too big\n", > + vaddr = dma_pool_alloc(atdma->memset_pool, GFP_ATOMIC, &paddr); Mostly people use _zalloc variant, any reason why you don't want that -- ~Vinod ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/2] dmaengine: hdmac: factorise memset descriptor allocation 2015-10-07 13:54 ` Vinod Koul @ 2015-10-07 17:33 ` Maxime Ripard -1 siblings, 0 replies; 12+ messages in thread From: Maxime Ripard @ 2015-10-07 17:33 UTC (permalink / raw) To: linux-arm-kernel Hi Vinod, On Wed, Oct 07, 2015 at 02:54:13PM +0100, Vinod Koul wrote: > On Thu, Oct 01, 2015 at 04:52:37PM +0200, Maxime Ripard wrote: > > > +static struct at_desc *atc_create_memset_desc(struct dma_chan *chan, > > + dma_addr_t psrc, > > + dma_addr_t pdst, > > + size_t len) > > +{ > > + struct at_dma_chan *atchan = to_at_dma_chan(chan); > > + struct at_desc *desc; > > + size_t xfer_count; > > + > > + u32 ctrla = ATC_SRC_WIDTH(2) | > > + ATC_DST_WIDTH(2); > > why is this over two lines :) > > > + u32 ctrlb = ATC_DEFAULT_CTRLB | ATC_IEN | > > + ATC_SRC_ADDR_MODE_FIXED | > > + ATC_DST_ADDR_MODE_INCR | > > + ATC_FC_MEM2MEM; > > + > > + xfer_count = len >> 2; > > + if (xfer_count > ATC_BTSIZE_MAX) { > > + dev_err(chan2dev(chan), "%s: buffer is too big\n", > > + __func__); > > + return NULL; > > + } > > This is fine, but this is driver limitation. We should really split the > txn to multiple descriptors here.. Both these things are actually just copy from the previous code. I can probably fix the first style issue in this patch, but splitting the memset descriptors should go in a separate patch. > > > @@ -914,46 +953,26 @@ atc_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value, > > return NULL; > > } > > > > - xfer_count = len >> 2; > > - if (xfer_count > ATC_BTSIZE_MAX) { > > - dev_err(chan2dev(chan), "%s: buffer is too big\n", > > + vaddr = dma_pool_alloc(atdma->memset_pool, GFP_ATOMIC, &paddr); > > Mostly people use _zalloc variant, any reason why you don't want that Not necessarily, but I don't need zeroed memory either, since I overwrite the content right after the allocation. Maxime -- Maxime Ripard, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20151007/77353878/attachment.sig> ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/2] dmaengine: hdmac: factorise memset descriptor allocation @ 2015-10-07 17:33 ` Maxime Ripard 0 siblings, 0 replies; 12+ messages in thread From: Maxime Ripard @ 2015-10-07 17:33 UTC (permalink / raw) To: Vinod Koul Cc: Nicolas Ferre, Alexandre Belloni, dmaengine, linux-kernel, linux-arm-kernel, Ludovic Desroches, Cyrille Pitchen [-- Attachment #1: Type: text/plain, Size: 1851 bytes --] Hi Vinod, On Wed, Oct 07, 2015 at 02:54:13PM +0100, Vinod Koul wrote: > On Thu, Oct 01, 2015 at 04:52:37PM +0200, Maxime Ripard wrote: > > > +static struct at_desc *atc_create_memset_desc(struct dma_chan *chan, > > + dma_addr_t psrc, > > + dma_addr_t pdst, > > + size_t len) > > +{ > > + struct at_dma_chan *atchan = to_at_dma_chan(chan); > > + struct at_desc *desc; > > + size_t xfer_count; > > + > > + u32 ctrla = ATC_SRC_WIDTH(2) | > > + ATC_DST_WIDTH(2); > > why is this over two lines :) > > > + u32 ctrlb = ATC_DEFAULT_CTRLB | ATC_IEN | > > + ATC_SRC_ADDR_MODE_FIXED | > > + ATC_DST_ADDR_MODE_INCR | > > + ATC_FC_MEM2MEM; > > + > > + xfer_count = len >> 2; > > + if (xfer_count > ATC_BTSIZE_MAX) { > > + dev_err(chan2dev(chan), "%s: buffer is too big\n", > > + __func__); > > + return NULL; > > + } > > This is fine, but this is driver limitation. We should really split the > txn to multiple descriptors here.. Both these things are actually just copy from the previous code. I can probably fix the first style issue in this patch, but splitting the memset descriptors should go in a separate patch. > > > @@ -914,46 +953,26 @@ atc_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value, > > return NULL; > > } > > > > - xfer_count = len >> 2; > > - if (xfer_count > ATC_BTSIZE_MAX) { > > - dev_err(chan2dev(chan), "%s: buffer is too big\n", > > + vaddr = dma_pool_alloc(atdma->memset_pool, GFP_ATOMIC, &paddr); > > Mostly people use _zalloc variant, any reason why you don't want that Not necessarily, but I don't need zeroed memory either, since I overwrite the content right after the allocation. Maxime -- Maxime Ripard, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 819 bytes --] ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/2] dmaengine: hdmac: factorise memset descriptor allocation 2015-10-07 17:33 ` Maxime Ripard @ 2015-10-09 15:29 ` Vinod Koul -1 siblings, 0 replies; 12+ messages in thread From: Vinod Koul @ 2015-10-09 15:29 UTC (permalink / raw) To: linux-arm-kernel On Wed, Oct 07, 2015 at 06:33:17PM +0100, Maxime Ripard wrote: > > This is fine, but this is driver limitation. We should really split the > > txn to multiple descriptors here.. > > Both these things are actually just copy from the previous code. > > I can probably fix the first style issue in this patch, but splitting > the memset descriptors should go in a separate patch. That sounds fine -- ~Vinod ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/2] dmaengine: hdmac: factorise memset descriptor allocation @ 2015-10-09 15:29 ` Vinod Koul 0 siblings, 0 replies; 12+ messages in thread From: Vinod Koul @ 2015-10-09 15:29 UTC (permalink / raw) To: Maxime Ripard Cc: Nicolas Ferre, Alexandre Belloni, dmaengine, linux-kernel, linux-arm-kernel, Ludovic Desroches, Cyrille Pitchen On Wed, Oct 07, 2015 at 06:33:17PM +0100, Maxime Ripard wrote: > > This is fine, but this is driver limitation. We should really split the > > txn to multiple descriptors here.. > > Both these things are actually just copy from the previous code. > > I can probably fix the first style issue in this patch, but splitting > the memset descriptors should go in a separate patch. That sounds fine -- ~Vinod ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 2/2] dmaengine: hdmac: Add scatter-gathered memset support 2015-10-01 14:52 ` Maxime Ripard @ 2015-10-01 14:52 ` Maxime Ripard -1 siblings, 0 replies; 12+ messages in thread From: Maxime Ripard @ 2015-10-01 14:52 UTC (permalink / raw) To: linux-arm-kernel Just like memset support, the HDMAC might be used to do a memset over a discontiguous memory area. In such a case, we'll just build up a chain of memset descriptors over the contiguous chunks of memory to set, in order to allow such a support. Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> --- drivers/dma/at_hdmac.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 009103fd6d9a..f19651645a33 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -987,6 +987,83 @@ err_free_buffer: return NULL; } +static struct dma_async_tx_descriptor * +atc_prep_dma_memset_sg(struct dma_chan *chan, + struct scatterlist *sgl, + unsigned int sg_len, int value, + unsigned long flags) +{ + struct at_dma_chan *atchan = to_at_dma_chan(chan); + struct at_dma *atdma = to_at_dma(chan->device); + struct at_desc *desc = NULL, *first = NULL, *prev = NULL; + struct scatterlist *sg; + void __iomem *vaddr; + dma_addr_t paddr; + size_t total_len = 0; + int i; + + dev_vdbg(chan2dev(chan), "%s: v0x%x l0x%zx f0x%lx\n", __func__, + value, sg_len, flags); + + if (unlikely(!sgl || !sg_len)) { + dev_dbg(chan2dev(chan), "%s: scatterlist is empty!\n", + __func__); + return NULL; + } + + vaddr = dma_pool_alloc(atdma->memset_pool, GFP_ATOMIC, &paddr); + if (!vaddr) { + dev_err(chan2dev(chan), "%s: couldn't allocate buffer\n", + __func__); + return NULL; + } + *(u32*)vaddr = value; + + for_each_sg(sgl, sg, sg_len, i) { + dma_addr_t dest = sg_dma_address(sg); + size_t len = sg_dma_len(sg); + + dev_vdbg(chan2dev(chan), "%s: d0x%08x, l0x%zx\n", + __func__, dest, len); + + if (!is_dma_fill_aligned(chan->device, dest, 0, len)) { + dev_err(chan2dev(chan), "%s: buffer is not aligned\n", + __func__); + goto err_put_desc; + } + + desc = atc_create_memset_desc(chan, paddr, dest, len); + if (!desc) + goto err_put_desc; + + atc_desc_chain(&first, &prev, desc); + + total_len += len; + } + + /* + * Only set the buffer pointers on the last descriptor to + * avoid free'ing while we have our transfer still going + */ + desc->memset_paddr = paddr; + desc->memset_vaddr = vaddr; + desc->memset_buffer = true; + + first->txd.cookie = -EBUSY; + first->total_len = total_len; + + /* set end-of-link on the descriptor */ + set_desc_eol(desc); + + first->txd.flags = flags; + + return &first->txd; + +err_put_desc: + atc_desc_put(atchan, first); + return NULL; +} + /** * atc_prep_slave_sg - prepare descriptors for a DMA_SLAVE transaction * @chan: DMA channel @@ -1869,6 +1946,7 @@ static int __init at_dma_probe(struct platform_device *pdev) dma_cap_set(DMA_INTERLEAVE, at91sam9g45_config.cap_mask); dma_cap_set(DMA_MEMCPY, at91sam9g45_config.cap_mask); dma_cap_set(DMA_MEMSET, at91sam9g45_config.cap_mask); + dma_cap_set(DMA_MEMSET_SG, at91sam9g45_config.cap_mask); dma_cap_set(DMA_PRIVATE, at91sam9g45_config.cap_mask); dma_cap_set(DMA_SLAVE, at91sam9g45_config.cap_mask); dma_cap_set(DMA_SG, at91sam9g45_config.cap_mask); @@ -1990,6 +2068,7 @@ static int __init at_dma_probe(struct platform_device *pdev) if (dma_has_cap(DMA_MEMSET, atdma->dma_common.cap_mask)) { atdma->dma_common.device_prep_dma_memset = atc_prep_dma_memset; + atdma->dma_common.device_prep_dma_memset_sg = atc_prep_dma_memset_sg; atdma->dma_common.fill_align = DMAENGINE_ALIGN_4_BYTES; } -- 2.5.3 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/2] dmaengine: hdmac: Add scatter-gathered memset support @ 2015-10-01 14:52 ` Maxime Ripard 0 siblings, 0 replies; 12+ messages in thread From: Maxime Ripard @ 2015-10-01 14:52 UTC (permalink / raw) To: Vinod Koul, Nicolas Ferre, Alexandre Belloni Cc: dmaengine, linux-kernel, linux-arm-kernel, Ludovic Desroches, Cyrille Pitchen, Maxime Ripard Just like memset support, the HDMAC might be used to do a memset over a discontiguous memory area. In such a case, we'll just build up a chain of memset descriptors over the contiguous chunks of memory to set, in order to allow such a support. Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> --- drivers/dma/at_hdmac.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 009103fd6d9a..f19651645a33 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -987,6 +987,83 @@ err_free_buffer: return NULL; } +static struct dma_async_tx_descriptor * +atc_prep_dma_memset_sg(struct dma_chan *chan, + struct scatterlist *sgl, + unsigned int sg_len, int value, + unsigned long flags) +{ + struct at_dma_chan *atchan = to_at_dma_chan(chan); + struct at_dma *atdma = to_at_dma(chan->device); + struct at_desc *desc = NULL, *first = NULL, *prev = NULL; + struct scatterlist *sg; + void __iomem *vaddr; + dma_addr_t paddr; + size_t total_len = 0; + int i; + + dev_vdbg(chan2dev(chan), "%s: v0x%x l0x%zx f0x%lx\n", __func__, + value, sg_len, flags); + + if (unlikely(!sgl || !sg_len)) { + dev_dbg(chan2dev(chan), "%s: scatterlist is empty!\n", + __func__); + return NULL; + } + + vaddr = dma_pool_alloc(atdma->memset_pool, GFP_ATOMIC, &paddr); + if (!vaddr) { + dev_err(chan2dev(chan), "%s: couldn't allocate buffer\n", + __func__); + return NULL; + } + *(u32*)vaddr = value; + + for_each_sg(sgl, sg, sg_len, i) { + dma_addr_t dest = sg_dma_address(sg); + size_t len = sg_dma_len(sg); + + dev_vdbg(chan2dev(chan), "%s: d0x%08x, l0x%zx\n", + __func__, dest, len); + + if (!is_dma_fill_aligned(chan->device, dest, 0, len)) { + dev_err(chan2dev(chan), "%s: buffer is not aligned\n", + __func__); + goto err_put_desc; + } + + desc = atc_create_memset_desc(chan, paddr, dest, len); + if (!desc) + goto err_put_desc; + + atc_desc_chain(&first, &prev, desc); + + total_len += len; + } + + /* + * Only set the buffer pointers on the last descriptor to + * avoid free'ing while we have our transfer still going + */ + desc->memset_paddr = paddr; + desc->memset_vaddr = vaddr; + desc->memset_buffer = true; + + first->txd.cookie = -EBUSY; + first->total_len = total_len; + + /* set end-of-link on the descriptor */ + set_desc_eol(desc); + + first->txd.flags = flags; + + return &first->txd; + +err_put_desc: + atc_desc_put(atchan, first); + return NULL; +} + /** * atc_prep_slave_sg - prepare descriptors for a DMA_SLAVE transaction * @chan: DMA channel @@ -1869,6 +1946,7 @@ static int __init at_dma_probe(struct platform_device *pdev) dma_cap_set(DMA_INTERLEAVE, at91sam9g45_config.cap_mask); dma_cap_set(DMA_MEMCPY, at91sam9g45_config.cap_mask); dma_cap_set(DMA_MEMSET, at91sam9g45_config.cap_mask); + dma_cap_set(DMA_MEMSET_SG, at91sam9g45_config.cap_mask); dma_cap_set(DMA_PRIVATE, at91sam9g45_config.cap_mask); dma_cap_set(DMA_SLAVE, at91sam9g45_config.cap_mask); dma_cap_set(DMA_SG, at91sam9g45_config.cap_mask); @@ -1990,6 +2068,7 @@ static int __init at_dma_probe(struct platform_device *pdev) if (dma_has_cap(DMA_MEMSET, atdma->dma_common.cap_mask)) { atdma->dma_common.device_prep_dma_memset = atc_prep_dma_memset; + atdma->dma_common.device_prep_dma_memset_sg = atc_prep_dma_memset_sg; atdma->dma_common.fill_align = DMAENGINE_ALIGN_4_BYTES; } -- 2.5.3 ^ permalink raw reply related [flat|nested] 12+ messages in thread
end of thread, other threads:[~2015-10-09 15:29 UTC | newest] Thread overview: 12+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2015-10-01 14:52 [PATCH 0/2] dmaengine: hdmac: Add scatter-gathered memset support Maxime Ripard 2015-10-01 14:52 ` Maxime Ripard 2015-10-01 14:52 ` [PATCH 1/2] dmaengine: hdmac: factorise memset descriptor allocation Maxime Ripard 2015-10-01 14:52 ` Maxime Ripard 2015-10-07 13:54 ` Vinod Koul 2015-10-07 13:54 ` Vinod Koul 2015-10-07 17:33 ` Maxime Ripard 2015-10-07 17:33 ` Maxime Ripard 2015-10-09 15:29 ` Vinod Koul 2015-10-09 15:29 ` Vinod Koul 2015-10-01 14:52 ` [PATCH 2/2] dmaengine: hdmac: Add scatter-gathered memset support Maxime Ripard 2015-10-01 14:52 ` Maxime Ripard
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.