DMA Engine development
 help / color / mirror / Atom feed
* dma: axi-dmac: Split too large segments
From: Lars-Peter Clausen @ 2019-02-18  7:34 UTC (permalink / raw)
  To: Ardelean, Alexandru, lkp@intel.com
  Cc: kbuild-all@01.org, dmaengine@vger.kernel.org, vkoul@kernel.org

On 2/18/19 8:28 AM, Ardelean, Alexandru wrote:
> On Sat, 2019-02-16 at 17:03 +0800, kbuild test robot wrote:
>>
> 
> My bad here.
> I took this patch from our kernel tree and sent it.
> I assumed it works, since it works in our tree.
> I'll take a look and see about the order of patches, and which one(s)
> need(s) to be sent before this one

https://github.com/analogdevicesinc/linux/commit/414a555896b2abca3518c3c878f21e7b1ea95904#diff-b5b2fd5430b4f9aff1ae97bae60dd5c5

That patch was sent upstream, not sure why it was never merged.

But if necessary you can also re-write this patch to not rely on the
other one.

^ permalink raw reply

* dma: axi-dmac: Split too large segments
From: Ardelean, Alexandru @ 2019-02-18  7:28 UTC (permalink / raw)
  To: lkp@intel.com
  Cc: kbuild-all@01.org, dmaengine@vger.kernel.org, vkoul@kernel.org,
	lars@metafoo.de

On Sat, 2019-02-16 at 17:03 +0800, kbuild test robot wrote:
> 

My bad here.
I took this patch from our kernel tree and sent it.
I assumed it works, since it works in our tree.
I'll take a look and see about the order of patches, and which one(s)
need(s) to be sent before this one

Thanks
Alex

> 
> Hi Lars-Peter,
> 
> I love your patch! Yet something to improve:
> 
> [auto build test ERROR on linus/master]
> [also build test ERROR on v5.0-rc4 next-20190215]
> [if your patch is applied to the wrong git tree, please drop us a note to
> help improve the system]
> 
> url:    
> https://github.com/0day-ci/linux/commits/Alexandru-Ardelean/dma-axi-dmac-Split-too-large-segments/20190216-160002
> config: nds32-allyesconfig (attached as .config)
> compiler: nds32le-linux-gcc (GCC) 6.4.0
> reproduce:
>         wget 
> https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross
> -O ~/bin/make.cross
>         chmod +x ~/bin/make.cross
>         # save the attached .config to linux build tree
>         GCC_VERSION=6.4.0 make.cross ARCH=nds32
> 
> All errors (new ones prefixed by >>):
> 
>    drivers//dma/dma-axi-dmac.c: In function 'axi_dmac_prep_slave_sg':
> > > drivers//dma/dma-axi-dmac.c:443:12: error: implicit declaration of
> > > function 'sg_nents_for_dma' [-Werror=implicit-function-declaration]
> 
>      num_sgs = sg_nents_for_dma(sgl, sg_len, chan->max_length);
>                ^~~~~~~~~~~~~~~~
>    cc1: some warnings being treated as errors
> 
> vim +/sg_nents_for_dma +443 drivers//dma/dma-axi-dmac.c
> 
>    427
>    428  static struct dma_async_tx_descriptor *axi_dmac_prep_slave_sg(
>    429          struct dma_chan *c, struct scatterlist *sgl,
>    430          unsigned int sg_len, enum dma_transfer_direction
> direction,
>    431          unsigned long flags, void *context)
>    432  {
>    433          struct axi_dmac_chan *chan = to_axi_dmac_chan(c);
>    434          struct axi_dmac_desc *desc;
>    435          struct axi_dmac_sg *dsg;
>    436          struct scatterlist *sg;
>    437          unsigned int num_sgs;
>    438          unsigned int i;
>    439
>    440          if (direction != chan->direction)
>    441                  return NULL;
>    442
>  > 443          num_sgs = sg_nents_for_dma(sgl, sg_len, chan-
> >max_length);
>    444          desc = axi_dmac_alloc_desc(num_sgs);
>    445          if (!desc)
>    446                  return NULL;
>    447
>    448          dsg = desc->sg;
>    449
>    450          for_each_sg(sgl, sg, sg_len, i) {
>    451                  if (!axi_dmac_check_addr(chan,
> sg_dma_address(sg)) ||
>    452                      !axi_dmac_check_len(chan, sg_dma_len(sg))) {
>    453                          kfree(desc);
>    454                          return NULL;
>    455                  }
>    456
>    457                  dsg = axi_dmac_fill_linear_sg(chan, direction,
> sg_dma_address(sg), 1,
>    458                          sg_dma_len(sg), dsg);
>    459          }
>    460
>    461          desc->cyclic = false;
>    462
>    463          return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
>    464  }
>    465
> 
> ---
> 0-DAY kernel test infrastructure                Open Source Technology
> Center
> https://lists.01.org/pipermail/kbuild-all                   Intel
> Corporation

^ permalink raw reply

* dma: axi-dmac: Split too large segments
From: kbuild test robot @ 2019-02-16 10:08 UTC (permalink / raw)
  To: Alexandru Ardelean; +Cc: kbuild-all, dmaengine, vkoul, Lars-Peter Clausen

Hi Lars-Peter,

I love your patch! Yet something to improve:

[auto build test ERROR on linus/master]
[also build test ERROR on v5.0-rc4 next-20190215]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Alexandru-Ardelean/dma-axi-dmac-Split-too-large-segments/20190216-160002
config: xtensa-allyesconfig (attached as .config)
compiler: xtensa-linux-gcc (GCC) 8.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=8.2.0 make.cross ARCH=xtensa 

All errors (new ones prefixed by >>):

   drivers/dma/dma-axi-dmac.c: In function 'axi_dmac_prep_slave_sg':
>> drivers/dma/dma-axi-dmac.c:443:12: error: implicit declaration of function 'sg_nents_for_dma'; did you mean 'sg_nents_for_len'? [-Werror=implicit-function-declaration]
     num_sgs = sg_nents_for_dma(sgl, sg_len, chan->max_length);
               ^~~~~~~~~~~~~~~~
               sg_nents_for_len
   cc1: some warnings being treated as errors

vim +443 drivers/dma/dma-axi-dmac.c

   427	
   428	static struct dma_async_tx_descriptor *axi_dmac_prep_slave_sg(
   429		struct dma_chan *c, struct scatterlist *sgl,
   430		unsigned int sg_len, enum dma_transfer_direction direction,
   431		unsigned long flags, void *context)
   432	{
   433		struct axi_dmac_chan *chan = to_axi_dmac_chan(c);
   434		struct axi_dmac_desc *desc;
   435		struct axi_dmac_sg *dsg;
   436		struct scatterlist *sg;
   437		unsigned int num_sgs;
   438		unsigned int i;
   439	
   440		if (direction != chan->direction)
   441			return NULL;
   442	
 > 443		num_sgs = sg_nents_for_dma(sgl, sg_len, chan->max_length);
   444		desc = axi_dmac_alloc_desc(num_sgs);
   445		if (!desc)
   446			return NULL;
   447	
   448		dsg = desc->sg;
   449	
   450		for_each_sg(sgl, sg, sg_len, i) {
   451			if (!axi_dmac_check_addr(chan, sg_dma_address(sg)) ||
   452			    !axi_dmac_check_len(chan, sg_dma_len(sg))) {
   453				kfree(desc);
   454				return NULL;
   455			}
   456	
   457			dsg = axi_dmac_fill_linear_sg(chan, direction, sg_dma_address(sg), 1,
   458				sg_dma_len(sg), dsg);
   459		}
   460	
   461		desc->cyclic = false;
   462	
   463		return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
   464	}
   465
---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

^ permalink raw reply

* ARM64 boot failure on espressobin with 5.0.0-rc6 (1f947a7a011fcceb14cb912f5481a53b18f1879a)
From: John David Anglin @ 2019-02-15 16:05 UTC (permalink / raw)
  To: Robin Murphy, Christoph Hellwig; +Cc: dmaengine, iommu, linux-arm-kernel

On 2019-02-14 12:58 p.m., Robin Murphy wrote:
> Hmm, having felt brave enough to take a closer look, it might actually be as simple as this - Dave, are you able to give the diff below a spin?
> 
> Robin.
> 
> ----->8-----
> diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
> index 7f595355fb79..fe4a7c71fede 100644
> --- a/drivers/dma/mv_xor.c
> +++ b/drivers/dma/mv_xor.c
> @@ -1059,6 +1059,7 @@ mv_xor_channel_add(struct mv_xor_device *xordev,
>          mv_chan->op_in_desc = XOR_MODE_IN_DESC;
> 
>      dma_dev = &mv_chan->dmadev;
> +    dma_dev->dev = &pdev->dev;
>      mv_chan->xordev = xordev;
> 
>      /*
> @@ -1091,7 +1092,6 @@ mv_xor_channel_add(struct mv_xor_device *xordev,
>      dma_dev->device_free_chan_resources = mv_xor_free_chan_resources;
>      dma_dev->device_tx_status = mv_xor_status;
>      dma_dev->device_issue_pending = mv_xor_issue_pending;
> -    dma_dev->dev = &pdev->dev;
> 
>      /* set prep routines based on capability */
>      if (dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask))

The patch is fine and it fixes the boot failure.

I misapplied it in previous test.

Thanks,
Dave

^ permalink raw reply

* ARM64 boot failure on espressobin with 5.0.0-rc6 (1f947a7a011fcceb14cb912f5481a53b18f1879a)
From: John David Anglin @ 2019-02-15 15:22 UTC (permalink / raw)
  To: Robin Murphy, Christoph Hellwig; +Cc: dmaengine, iommu, linux-arm-kernel

On 2019-02-14 12:58 p.m., Robin Murphy wrote:
> Hmm, having felt brave enough to take a closer look, it might actually be as simple as this - Dave, are you able to give the diff below a spin?
Still crashes but in slightly different spot:

[    0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
[    0.000000] Linux version 5.0.0-rc6+ (root@espressobin) (gcc version 6.3.0 20170516 (Debian 6.3.0-18+deb9u1)) #1 SMP PREEMPT Wed Feb 13
16:17:46 EST 2019
[    0.000000] Machine model: Globalscale Marvell ESPRESSOBin Board
[    0.000000] earlycon: ar3700_uart0 at MMIO 0x00000000d0012000 (options '')
[    0.000000] printk: bootconsole [ar3700_uart0] enabled
[    3.210276] Internal error: Oops: 96000045 [#1] PREEMPT SMP
[    3.215932] Modules linked in:
[    3.219072] CPU: 1 PID: 1 Comm: swapper/0 Not tainted 5.0.0-rc6+ #1
[    3.225519] Hardware name: Globalscale Marvell ESPRESSOBin Board (DT)
[    3.232151] pstate: a0000005 (NzCv daif -PAN -UAO)
[    3.237090] pc : mv_xor_channel_add+0x4c/0xb28
[    3.241650] lr : mv_xor_probe+0x20c/0x4b8
[    3.245768] sp : ffffff8010033ac0
[    3.249173] x29: ffffff8010033ac0 x28: 0000000000000000
[    3.254639] x27: ffffff8010e76068 x26: 0000000000000029
[    3.260104] x25: 0000000000000000 x24: 0000000000000000
[    3.265570] x23: ffffffc03fb47400 x22: ffffff8010ead000
[    3.271035] x21: ffffffc03fb47410 x20: ffffffc03bea8d80
[    3.276501] x19: ffffffc03fb47400 x18: ffffffffffffffff
[    3.281966] x17: 000000000000000c x16: 000000000000000a
[    3.287432] x15: ffffff8010ead6c8 x14: ffffffc03beaa003
[    3.292898] x13: ffffffc03beaa002 x12: 0000000000000038
[    3.298363] x11: 0000000000001fff x10: 0000000000000001
[    3.303829] x9 : 0000000000000040 x8 : ffffff8010ec7928
[    3.309294] x7 : ffffffc03cc003b8 x6 : 0000000000000000
[    3.314760] x5 : 0000000000000000 x4 : 0000000000000029
[    3.320226] x3 : 0000000000000083 x2 : 00000000000080c0
[    3.325691] x1 : 0000000000000000 x0 : ffffffc03fb47410
[    3.331158] Process swapper/0 (pid: 1, stack limit = 0x(____ptrval____))
[    3.338056] Call trace:
[    3.340569]  mv_xor_channel_add+0x4c/0xb28
[    3.344779]  mv_xor_probe+0x20c/0x4b8
[    3.348544]  platform_drv_probe+0x50/0xb0
[    3.352663]  really_probe+0x1fc/0x2c0
[    3.356427]  driver_probe_device+0x58/0x100
[    3.360727]  __driver_attach+0xd8/0xe0
[    3.364580]  bus_for_each_dev+0x68/0xc8
[    3.368522]  driver_attach+0x20/0x28
[    3.372196]  bus_add_driver+0x108/0x228
[    3.376139]  driver_register+0x60/0x110
[    3.380081]  __platform_driver_register+0x44/0x50
[    3.384923]  mv_xor_driver_init+0x18/0x20
[    3.389043]  do_one_initcall+0x58/0x170
[    3.392985]  kernel_init_freeable+0x190/0x234
[    3.397465]  kernel_init+0x10/0x108
[    3.401047]  ret_from_fork+0x10/0x1c
[    3.404723] Code: f90067a5 d2800005 52901802 aa1503e0 (f9003035)
[    3.411004] ---[ end trace 65be82a62724e328 ]---
[    3.415804] Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
[    3.423626] SMP: stopping secondary CPUs
[    3.427661] Kernel Offset: disabled
[    3.431243] CPU features: 0x002,2000200c
[    3.435272] Memory Limit: none
[    3.438412] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b ]---

ffffff8010630440 <mv_xor_channel_add>:
ffffff8010630440:       a9b37bfd        stp     x29, x30, [sp, #-208]!
ffffff8010630444:       910003fd        mov     x29, sp
ffffff8010630448:       a9025bf5        stp     x21, x22, [sp, #32]
ffffff801063044c:       b00043f6        adrp    x22, ffffff8010ead000 <crypto_il_tab+0x940>
ffffff8010630450:       a90363f7        stp     x23, x24, [sp, #48]
ffffff8010630454:       aa0103f7        mov     x23, x1
ffffff8010630458:       a9046bf9        stp     x25, x26, [sp, #64]
ffffff801063045c:       d2800001        mov     x1, #0x0                        // #0
ffffff8010630460:       a90153f3        stp     x19, x20, [sp, #16]
ffffff8010630464:       910042f5        add     x21, x23, #0x10
ffffff8010630468:       a90573fb        stp     x27, x28, [sp, #80]
ffffff801063046c:       aa0003f4        mov     x20, x0
ffffff8010630470:       911b22c0        add     x0, x22, #0x6c8
ffffff8010630474:       2a0203f9        mov     w25, w2
ffffff8010630478:       f9400005        ldr     x5, [x0]
ffffff801063047c:       f90067a5        str     x5, [x29, #200]
ffffff8010630480:       d2800005        mov     x5, #0x0                        // #0
ffffff8010630484:       52901802        mov     w2, #0x80c0                     // #32960
ffffff8010630488:       aa1503e0        mov     x0, x21
ffffff801063048c:       f9003035        str     x21, [x1, #96]
ffffff8010630490:       72a00c02        movk    w2, #0x60, lsl #16
ffffff8010630494:       d2806a01        mov     x1, #0x350                     
...

Dave

-- 
John David Anglin  dave.anglin@bell.net

^ permalink raw reply

* dma: axi-dmac: Split too large segments
From: Alexandru Ardelean @ 2019-02-15 11:06 UTC (permalink / raw)
  To: dmaengine, vkoul; +Cc: Lars-Peter Clausen, Alexandru Ardelean

From: Lars-Peter Clausen <lars@metafoo.de>

The axi-dmac driver currently rejects transfers with segments that are
larger than what the hardware can handle.

Re-work the driver so that these large segments are split into multiple
segments instead where each segment is smaller or equal to the maximum
segment size.

This allows the driver to handle transfers with segments of arbitrary size.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/dma/dma-axi-dmac.c | 80 ++++++++++++++++++++++++++++----------
 1 file changed, 60 insertions(+), 20 deletions(-)

diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c
index ffc0adc2f6ce..6a41e1f49077 100644
--- a/drivers/dma/dma-axi-dmac.c
+++ b/drivers/dma/dma-axi-dmac.c
@@ -83,6 +83,7 @@ struct axi_dmac_sg {
 	unsigned int dest_stride;
 	unsigned int src_stride;
 	unsigned int id;
+	bool last;
 	bool schedule_when_free;
 };
 
@@ -166,7 +167,7 @@ static int axi_dmac_dest_is_mem(struct axi_dmac_chan *chan)
 
 static bool axi_dmac_check_len(struct axi_dmac_chan *chan, unsigned int len)
 {
-	if (len == 0 || len > chan->max_length)
+	if (len == 0)
 		return false;
 	if ((len & chan->align_mask) != 0) /* Not aligned */
 		return false;
@@ -379,6 +380,50 @@ static struct axi_dmac_desc *axi_dmac_alloc_desc(unsigned int num_sgs)
 	return desc;
 }
 
+static struct axi_dmac_sg *axi_dmac_fill_linear_sg(struct axi_dmac_chan *chan,
+	enum dma_transfer_direction direction, dma_addr_t addr,
+	unsigned int num_periods, unsigned int period_len,
+	struct axi_dmac_sg *sg)
+{
+	unsigned int num_segments, i;
+	unsigned int segment_size;
+	unsigned int len;
+
+	/* Split into multiple equally sized segments if necessary */
+	num_segments = DIV_ROUND_UP(period_len, chan->max_length);
+	segment_size = DIV_ROUND_UP(period_len, num_segments);
+	/* Take care of alignment */
+	segment_size = ((segment_size - 1) | chan->align_mask) + 1;
+
+	for (i = 0; i < num_periods; i++) {
+		len = period_len;
+
+		while (len > segment_size) {
+			if (direction == DMA_DEV_TO_MEM)
+				sg->dest_addr = addr;
+			else
+				sg->src_addr = addr;
+			sg->x_len = segment_size;
+			sg->y_len = 1;
+			sg++;
+			addr += segment_size;
+			len -= segment_size;
+		}
+
+		if (direction == DMA_DEV_TO_MEM)
+			sg->dest_addr = addr;
+		else
+			sg->src_addr = addr;
+		sg->x_len = len;
+		sg->y_len = 1;
+		sg->last = true;
+		sg++;
+		addr += len;
+	}
+
+	return sg;
+}
+
 static struct dma_async_tx_descriptor *axi_dmac_prep_slave_sg(
 	struct dma_chan *c, struct scatterlist *sgl,
 	unsigned int sg_len, enum dma_transfer_direction direction,
@@ -386,16 +431,21 @@ static struct dma_async_tx_descriptor *axi_dmac_prep_slave_sg(
 {
 	struct axi_dmac_chan *chan = to_axi_dmac_chan(c);
 	struct axi_dmac_desc *desc;
+	struct axi_dmac_sg *dsg;
 	struct scatterlist *sg;
+	unsigned int num_sgs;
 	unsigned int i;
 
 	if (direction != chan->direction)
 		return NULL;
 
-	desc = axi_dmac_alloc_desc(sg_len);
+	num_sgs = sg_nents_for_dma(sgl, sg_len, chan->max_length);
+	desc = axi_dmac_alloc_desc(num_sgs);
 	if (!desc)
 		return NULL;
 
+	dsg = desc->sg;
+
 	for_each_sg(sgl, sg, sg_len, i) {
 		if (!axi_dmac_check_addr(chan, sg_dma_address(sg)) ||
 		    !axi_dmac_check_len(chan, sg_dma_len(sg))) {
@@ -403,12 +453,8 @@ static struct dma_async_tx_descriptor *axi_dmac_prep_slave_sg(
 			return NULL;
 		}
 
-		if (direction == DMA_DEV_TO_MEM)
-			desc->sg[i].dest_addr = sg_dma_address(sg);
-		else
-			desc->sg[i].src_addr = sg_dma_address(sg);
-		desc->sg[i].x_len = sg_dma_len(sg);
-		desc->sg[i].y_len = 1;
+		dsg = axi_dmac_fill_linear_sg(chan, direction, sg_dma_address(sg), 1,
+			sg_dma_len(sg), dsg);
 	}
 
 	desc->cyclic = false;
@@ -423,7 +469,7 @@ static struct dma_async_tx_descriptor *axi_dmac_prep_dma_cyclic(
 {
 	struct axi_dmac_chan *chan = to_axi_dmac_chan(c);
 	struct axi_dmac_desc *desc;
-	unsigned int num_periods, i;
+	unsigned int num_periods, num_segments;
 
 	if (direction != chan->direction)
 		return NULL;
@@ -436,20 +482,14 @@ static struct dma_async_tx_descriptor *axi_dmac_prep_dma_cyclic(
 		return NULL;
 
 	num_periods = buf_len / period_len;
+	num_segments = DIV_ROUND_UP(period_len, chan->max_length);
 
-	desc = axi_dmac_alloc_desc(num_periods);
+	desc = axi_dmac_alloc_desc(num_periods * num_segments);
 	if (!desc)
 		return NULL;
 
-	for (i = 0; i < num_periods; i++) {
-		if (direction == DMA_DEV_TO_MEM)
-			desc->sg[i].dest_addr = buf_addr;
-		else
-			desc->sg[i].src_addr = buf_addr;
-		desc->sg[i].x_len = period_len;
-		desc->sg[i].y_len = 1;
-		buf_addr += period_len;
-	}
+	axi_dmac_fill_linear_sg(chan, direction, buf_addr, num_periods,
+		buf_len, desc->sg);
 
 	desc->cyclic = true;
 
@@ -647,7 +687,7 @@ static int axi_dmac_probe(struct platform_device *pdev)
 	of_node_put(of_channels);
 
 	pdev->dev.dma_parms = &dmac->dma_parms;
-	dma_set_max_seg_size(&pdev->dev, dmac->chan.max_length);
+	dma_set_max_seg_size(&pdev->dev, UINT_MAX);
 
 	dma_dev = &dmac->dma_dev;
 	dma_cap_set(DMA_SLAVE, dma_dev->cap_mask);

^ permalink raw reply related

* dma: axi-dmac: assign `copy_align` property
From: Alexandru Ardelean @ 2019-02-15 11:02 UTC (permalink / raw)
  To: dmaengine, vkoul; +Cc: Alexandru Ardelean

The `copy_align` property is a generic property that describes alignment
for DMA memcpy & sg ops.
It serves mostly an informational purpose, and can be used in DMA tests, to
pass the info to know what alignment to expect.

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/dma/dma-axi-dmac.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c
index a54157ab00b2..a58aee7090dd 100644
--- a/drivers/dma/dma-axi-dmac.c
+++ b/drivers/dma/dma-axi-dmac.c
@@ -814,6 +814,8 @@ static int axi_dmac_probe(struct platform_device *pdev)
 	if (ret)
 		goto err_clk_disable;
 
+	dma_dev->copy_align = (dmac->chan.address_align_mask + 1);
+
 	axi_dmac_write(dmac, AXI_DMAC_REG_IRQ_MASK, 0x00);
 
 	ret = dma_async_device_register(dma_dev);

^ permalink raw reply related

* [2/2] dma: axi-dmac: report DMA_INTERLEAVE capability
From: Alexandru Ardelean @ 2019-02-15  9:17 UTC (permalink / raw)
  To: dmaengine, vkoul; +Cc: Dragos Bogdan, Alexandru Ardelean

From: Dragos Bogdan <dragos.bogdan@analog.com>

Fixes commit 0e3b67b348b8 ("dmaengine: Add support for the Analog Devices
AXI-DMAC DMA controller")

The `device_prep_interleaved_dma()` callback is already present since the
driver was submitted initially.
This change adds the DMA_INTERLEAVE capability to the capability mask of
the DMA engine.

Signed-off-by: Dragos Bogdan <dragos.bogdan@analog.com>
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/dma/dma-axi-dmac.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c
index 2c999113b989..b2039e60ae04 100644
--- a/drivers/dma/dma-axi-dmac.c
+++ b/drivers/dma/dma-axi-dmac.c
@@ -652,6 +652,7 @@ static int axi_dmac_probe(struct platform_device *pdev)
 	dma_dev = &dmac->dma_dev;
 	dma_cap_set(DMA_SLAVE, dma_dev->cap_mask);
 	dma_cap_set(DMA_CYCLIC, dma_dev->cap_mask);
+	dma_cap_set(DMA_INTERLEAVE, dma_dev->cap_mask);
 	dma_dev->device_free_chan_resources = axi_dmac_free_chan_resources;
 	dma_dev->device_tx_status = dma_cookie_status;
 	dma_dev->device_issue_pending = axi_dmac_issue_pending;

^ permalink raw reply related

* [1/2] dma: axi-dmac: don't check the number of frames for alignment
From: Alexandru Ardelean @ 2019-02-15  9:17 UTC (permalink / raw)
  To: dmaengine, vkoul; +Cc: Alexandru Ardelean

Fixes commit 0e3b67b348b8 ("dmaengine: Add support for the Analog Devices
AXI-DMAC DMA controller")

For 2D transfers, there is no requirement for Y_LENGTH to be aligned
to the bus-width (or anything). X_LENGTH is required to be aligned
though.

So, we shouldn't check that the number of frames is aligned.

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/dma/dma-axi-dmac.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c
index ffc0adc2f6ce..2c999113b989 100644
--- a/drivers/dma/dma-axi-dmac.c
+++ b/drivers/dma/dma-axi-dmac.c
@@ -485,7 +485,7 @@ static struct dma_async_tx_descriptor *axi_dmac_prep_interleaved(
 
 	if (chan->hw_2d) {
 		if (!axi_dmac_check_len(chan, xt->sgl[0].size) ||
-		    !axi_dmac_check_len(chan, xt->numf))
+		    xt->numf == 0)
 			return NULL;
 		if (xt->sgl[0].size + dst_icg > chan->max_length ||
 		    xt->sgl[0].size + src_icg > chan->max_length)

^ permalink raw reply related

* ARM64 boot failure on espressobin with 5.0.0-rc6 (1f947a7a011fcceb14cb912f5481a53b18f1879a)
From: John David Anglin @ 2019-02-14 18:11 UTC (permalink / raw)
  To: Robin Murphy, Christoph Hellwig; +Cc: dmaengine, iommu, linux-arm-kernel

On 2019-02-14 12:58 p.m., Robin Murphy wrote:
> Hmm, having felt brave enough to take a closer look, it might actually be as simple as this - Dave, are you able to give the diff below a spin?
Yes.

^ permalink raw reply

* ARM64 boot failure on espressobin with 5.0.0-rc6 (1f947a7a011fcceb14cb912f5481a53b18f1879a)
From: Robin Murphy @ 2019-02-14 17:58 UTC (permalink / raw)
  To: Christoph Hellwig, John David Anglin; +Cc: dmaengine, iommu, linux-arm-kernel

On 14/02/2019 17:36, Christoph Hellwig wrote:
> On Thu, Feb 14, 2019 at 05:27:41PM +0000, Robin Murphy wrote:
>> Oh wow, that driver has possibly the most inventive way of passing a NULL
>> device to the DMA API that I've ever seen, and on arm64 it will certainly
>> have been failing since 4.2, but of course there's also no error checking
>> for anyone to notice...
> 
> I did take a brief look and didn't see how we got the NULL device
> pointer, so it is well hidden for sure.
> 
>> This crash will be a fallout from 356da6d0cd (plus the subsequent fix in
>> 9ab91e7c5c51) that's otherwise missed Christoph's big cleanup. Obviously
>> the right thing to do is for someone to try to figure out the steaming pile
>> of mess in that driver, but if necessary I think the quick fix below should
>> probably suffice to mitigate the change in the short term.
> 
> The fix looks ok.  And for 5.2 I plan to explicitly reject all uses of
> NULL device arguments in the DMA API.  I've sent patches out for all
> the obviously problemetic drivers, and most of them got accepted by the
> maintainers for the 5.1 merge window.
> 
> It seems like the mv_xor code is mostly unmaintained as far as I can
> tell unfortunately.

Hmm, having felt brave enough to take a closer look, it might actually 
be as simple as this - Dave, are you able to give the diff below a spin?

Robin.

----->8-----

diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index 7f595355fb79..fe4a7c71fede 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -1059,6 +1059,7 @@ mv_xor_channel_add(struct mv_xor_device *xordev,
  		mv_chan->op_in_desc = XOR_MODE_IN_DESC;

  	dma_dev = &mv_chan->dmadev;
+	dma_dev->dev = &pdev->dev;
  	mv_chan->xordev = xordev;

  	/*
@@ -1091,7 +1092,6 @@ mv_xor_channel_add(struct mv_xor_device *xordev,
  	dma_dev->device_free_chan_resources = mv_xor_free_chan_resources;
  	dma_dev->device_tx_status = mv_xor_status;
  	dma_dev->device_issue_pending = mv_xor_issue_pending;
-	dma_dev->dev = &pdev->dev;

  	/* set prep routines based on capability */
  	if (dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask))

^ permalink raw reply related

* ARM64 boot failure on espressobin with 5.0.0-rc6 (1f947a7a011fcceb14cb912f5481a53b18f1879a)
From: Christoph Hellwig @ 2019-02-14 17:36 UTC (permalink / raw)
  To: Robin Murphy
  Cc: Christoph Hellwig, dmaengine, iommu, John David Anglin,
	linux-arm-kernel

On Thu, Feb 14, 2019 at 05:27:41PM +0000, Robin Murphy wrote:
> Oh wow, that driver has possibly the most inventive way of passing a NULL 
> device to the DMA API that I've ever seen, and on arm64 it will certainly 
> have been failing since 4.2, but of course there's also no error checking 
> for anyone to notice...

I did take a brief look and didn't see how we got the NULL device
pointer, so it is well hidden for sure.

> This crash will be a fallout from 356da6d0cd (plus the subsequent fix in 
> 9ab91e7c5c51) that's otherwise missed Christoph's big cleanup. Obviously 
> the right thing to do is for someone to try to figure out the steaming pile 
> of mess in that driver, but if necessary I think the quick fix below should 
> probably suffice to mitigate the change in the short term.

The fix looks ok.  And for 5.2 I plan to explicitly reject all uses of
NULL device arguments in the DMA API.  I've sent patches out for all
the obviously problemetic drivers, and most of them got accepted by the
maintainers for the 5.1 merge window.

It seems like the mv_xor code is mostly unmaintained as far as I can
tell unfortunately.

^ permalink raw reply

* ARM64 boot failure on espressobin with 5.0.0-rc6 (1f947a7a011fcceb14cb912f5481a53b18f1879a)
From: Robin Murphy @ 2019-02-14 17:27 UTC (permalink / raw)
  To: Christoph Hellwig, dmaengine, iommu; +Cc: John David Anglin, linux-arm-kernel

On 14/02/2019 16:09, John David Anglin wrote:
> Starting kernel ...
> 
> [    0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
> [    0.000000] Linux version 5.0.0-rc6+ (root@espressobin) (gcc version 6.3.0 20170516 (Debian 6.3.0-18+deb9u1)) #1 SMP PREEMPT Wed Feb 13
> 16:17:46 EST 2019
> [    0.000000] Machine model: Globalscale Marvell ESPRESSOBin Board
> [    0.000000] earlycon: ar3700_uart0 at MMIO 0x00000000d0012000 (options '')
> [    0.000000] printk: bootconsole [ar3700_uart0] enabled
> [    3.219693] Internal error: Oops: 96000005 [#1] PREEMPT SMP
> [    3.225349] Modules linked in:
> [    3.228489] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.0.0-rc6+ #1
> [    3.234936] Hardware name: Globalscale Marvell ESPRESSOBin Board (DT)
> [    3.241568] pstate: 20000005 (nzCv daif -PAN -UAO)
> [    3.246505] pc : dma_direct_map_page+0x48/0x1d8
> [    3.251159] lr : mv_xor_channel_add+0x3b0/0xb28
> [    3.255812] sp : ffffff8010033a60
> [    3.259217] x29: ffffff8010033a60 x28: ffffffc03befec80
> [    3.264682] x27: ffffff8010e97068 x26: 0000000000000000
> [    3.270148] x25: 0000000000000029 x24: 0000000000000083
> [    3.275613] x23: 0000000000000000 x22: 0000000000000002
> [    3.281079] x21: 0000000000000080 x20: ffffff8010ecd000
> [    3.286544] x19: 0000000000000000 x18: ffffffffffffffff
> [    3.292010] x17: 00000000f8f63085 x16: 0000000074242664
> [    3.297476] x15: ffffff8010ecd6c8 x14: ffffffc03bed9e83
> [    3.302941] x13: ffffffc03bed9e82 x12: 0000000000000038
> [    3.308407] x11: 0000000000001fff x10: 0000000000000001
> [    3.313872] x9 : 0000000000000000 x8 : ffffff8010dbe000
> [    3.319338] x7 : ffffff8010fbe000 x6 : ffffffbf00000000
> [    3.324804] x5 : 0000000000000000 x4 : 0000000000000002
> [    3.330269] x3 : 0000000000000002 x2 : 0000000000000eac
> [    3.335735] x1 : ffffffbf00efbf80 x0 : 0000000000000000
> [    3.341202] Process swapper/0 (pid: 1, stack limit = 0x(____ptrval____))
> [    3.348100] Call trace:
> [    3.350612]  dma_direct_map_page+0x48/0x1d8
> [    3.354912]  mv_xor_channel_add+0x3b0/0xb28
> [    3.359213]  mv_xor_probe+0x20c/0x4b8
> [    3.362978]  platform_drv_probe+0x50/0xb0
> [    3.367097]  really_probe+0x1fc/0x2c0
> [    3.370860]  driver_probe_device+0x58/0x100
> [    3.375160]  __driver_attach+0xd8/0xe0
> [    3.379016]  bus_for_each_dev+0x68/0xc8
> [    3.382957]  driver_attach+0x20/0x28
> [    3.386631]  bus_add_driver+0x108/0x228
> [    3.390572]  driver_register+0x60/0x110
> [    3.394515]  __platform_driver_register+0x44/0x50
> [    3.399357]  mv_xor_driver_init+0x18/0x20
> [    3.403477]  do_one_initcall+0x58/0x170
> [    3.407419]  kernel_init_freeable+0x190/0x234
> [    3.411900]  kernel_init+0x10/0x108
> [    3.415482]  ret_from_fork+0x10/0x1c
> [    3.419157] Code: 2a0403f6 934cfc00 aa0503f7 7100047f (f9412663)
> [    3.425438] ---[ end trace f62a451df663a071 ]---
> [    3.430228] Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
> [    3.438060] SMP: stopping secondary CPUs
> [    3.442093] Kernel Offset: disabled
> [    3.445676] CPU features: 0x002,2000200c
> [    3.449706] Memory Limit: none
> [    3.452846] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b ]---
> 
> The same error occurs with linux-net 5.0.0-rc5 (91986ee166cf0816ae92668476ea7872d51b0c6e).  v4.20.x
> boots okay.  Seems to be a hard failure.

Oh wow, that driver has possibly the most inventive way of passing a 
NULL device to the DMA API that I've ever seen, and on arm64 it will 
certainly have been failing since 4.2, but of course there's also no 
error checking for anyone to notice...

This crash will be a fallout from 356da6d0cd (plus the subsequent fix in 
9ab91e7c5c51) that's otherwise missed Christoph's big cleanup. Obviously 
the right thing to do is for someone to try to figure out the steaming 
pile of mess in that driver, but if necessary I think the quick fix 
below should probably suffice to mitigate the change in the short term.

Robin.

----->8-----
  void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,

diff --git a/arch/arm64/include/asm/dma-mapping.h 
b/arch/arm64/include/asm/dma-mapping.h
index 95dbf3ef735a..f530edfe5678 100644
--- a/arch/arm64/include/asm/dma-mapping.h
+++ b/arch/arm64/include/asm/dma-mapping.h
@@ -26,7 +26,7 @@

  static inline const struct dma_map_ops *get_arch_dma_ops(struct 
bus_type *bus)
  {
-	return NULL;
+	return bus ? NULL : &dma_dummy_ops;
  }


^ permalink raw reply related

* [v10,3/3] dt-bindings: dma: uart: rename binding
From: Matthias Brugger @ 2019-02-14 10:13 UTC (permalink / raw)
  To: Long Cheng, Vinod Koul, Randy Dunlap, Rob Herring, Mark Rutland,
	Ryder Lee, Sean Wang, Nicolas Boichat
  Cc: Dan Williams, Greg Kroah-Hartman, Jiri Slaby, Sean Wang,
	dmaengine, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel, linux-serial, srv_heupstream, Yingjoe Chen, YT Shen,
	Zhenbao Liu

On 18/01/2019 04:10, Long Cheng wrote:
> The filename matches mtk-uart-apdma.c.
> So using "mtk-uart-apdma.txt" should be better.
> 
> Signed-off-by: Long Cheng <long.cheng@mediatek.com>
> ---
>  .../devicetree/bindings/dma/8250_mtk_dma.txt       |   33 --------------------
>  .../devicetree/bindings/dma/mtk-uart-apdma.txt     |   33 ++++++++++++++++++++
>  2 files changed, 33 insertions(+), 33 deletions(-)
>  delete mode 100644 Documentation/devicetree/bindings/dma/8250_mtk_dma.txt
>  create mode 100644 Documentation/devicetree/bindings/dma/mtk-uart-apdma.txt
> 
> diff --git a/Documentation/devicetree/bindings/dma/8250_mtk_dma.txt b/Documentation/devicetree/bindings/dma/8250_mtk_dma.txt
> deleted file mode 100644
> index 3fe0961..0000000
> --- a/Documentation/devicetree/bindings/dma/8250_mtk_dma.txt
> +++ /dev/null
> @@ -1,33 +0,0 @@
> -* Mediatek UART APDMA Controller
> -
> -Required properties:
> -- compatible should contain:
> -  * "mediatek,mt2712-uart-dma" for MT2712 compatible APDMA
> -  * "mediatek,mt6577-uart-dma" for MT6577 and all of the above
> -
> -- reg: The base address of the APDMA register bank.> -
> -- interrupts: A single interrupt specifier.

One interrupt per dma-request, or 8 if no dma-requests property is present.

> -
> -- clocks : Must contain an entry for each entry in clock-names.
> -  See ../clocks/clock-bindings.txt for details.
> -- clock-names: The APDMA clock for register accesses> -
> -Examples:
> -
> -	apdma: dma-controller@11000380 {
> -		compatible = "mediatek,mt2712-uart-dma";
> -		reg = <0 0x11000380 0 0x400>;
> -		interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_LOW>,
> -			     <GIC_SPI 64 IRQ_TYPE_LEVEL_LOW>,
> -			     <GIC_SPI 65 IRQ_TYPE_LEVEL_LOW>,
> -			     <GIC_SPI 66 IRQ_TYPE_LEVEL_LOW>,
> -			     <GIC_SPI 67 IRQ_TYPE_LEVEL_LOW>,
> -			     <GIC_SPI 68 IRQ_TYPE_LEVEL_LOW>,
> -			     <GIC_SPI 69 IRQ_TYPE_LEVEL_LOW>,
> -			     <GIC_SPI 70 IRQ_TYPE_LEVEL_LOW>;
> -		clocks = <&pericfg CLK_PERI_AP_DMA>;
> -		clock-names = "apdma";
> -		#dma-cells = <1>;
> -	};
> -
> diff --git a/Documentation/devicetree/bindings/dma/mtk-uart-apdma.txt b/Documentation/devicetree/bindings/dma/mtk-uart-apdma.txt
> new file mode 100644
> index 0000000..3fe0961
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/dma/mtk-uart-apdma.txt
> @@ -0,0 +1,33 @@
> +* Mediatek UART APDMA Controller
> +
> +Required properties:
> +- compatible should contain:
> +  * "mediatek,mt2712-uart-dma" for MT2712 compatible APDMA
> +  * "mediatek,mt6577-uart-dma" for MT6577 and all of the above
> +
> +- reg: The base address of the APDMA register bank.
> +

There is one address needed for every dma-request or 8 if dma-requests property
is not present. As already mentioned in the driver review dma-requests property
is missing.

> +- interrupts: A single interrupt specifier.
> +
> +- clocks : Must contain an entry for each entry in clock-names.
> +  See ../clocks/clock-bindings.txt for details.
> +- clock-names: The APDMA clock for register accesses
> +

Missing option property dma-33bits (should be mtk,dma-33bits?).

> +Examples:
> +
> +	apdma: dma-controller@11000380 {
> +		compatible = "mediatek,mt2712-uart-dma";
> +		reg = <0 0x11000380 0 0x400>;

We are missing the io mem areas here, right?

Regards,
Matthias

> +		interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_LOW>,
> +			     <GIC_SPI 64 IRQ_TYPE_LEVEL_LOW>,
> +			     <GIC_SPI 65 IRQ_TYPE_LEVEL_LOW>,
> +			     <GIC_SPI 66 IRQ_TYPE_LEVEL_LOW>,
> +			     <GIC_SPI 67 IRQ_TYPE_LEVEL_LOW>,
> +			     <GIC_SPI 68 IRQ_TYPE_LEVEL_LOW>,
> +			     <GIC_SPI 69 IRQ_TYPE_LEVEL_LOW>,
> +			     <GIC_SPI 70 IRQ_TYPE_LEVEL_LOW>;
> +		clocks = <&pericfg CLK_PERI_AP_DMA>;
> +		clock-names = "apdma";
> +		#dma-cells = <1>;
> +	};
> +
>

^ permalink raw reply

* [v10,1/3] dmaengine: 8250_mtk_dma: add MediaTek uart DMA support
From: Matthias Brugger @ 2019-02-14 10:08 UTC (permalink / raw)
  To: Long Cheng, Vinod Koul, Randy Dunlap, Rob Herring, Mark Rutland,
	Ryder Lee, Sean Wang, Nicolas Boichat
  Cc: Dan Williams, Greg Kroah-Hartman, Jiri Slaby, Sean Wang,
	dmaengine, devicetree, linux-arm-kernel, linux-mediatek,
	linux-kernel, linux-serial, srv_heupstream, Yingjoe Chen, YT Shen,
	Zhenbao Liu

On 18/01/2019 04:10, Long Cheng wrote:
> In DMA engine framework, add 8250 uart dma to support MediaTek uart.
> If MediaTek uart enabled(SERIAL_8250_MT6577), and want to improve
> the performance, can enable the function.
> 
> Signed-off-by: Long Cheng <long.cheng@mediatek.com>
> ---
>  drivers/dma/mediatek/Kconfig          |   11 +
>  drivers/dma/mediatek/Makefile         |    1 +
>  drivers/dma/mediatek/mtk-uart-apdma.c |  669 +++++++++++++++++++++++++++++++++
>  3 files changed, 681 insertions(+)
>  create mode 100644 drivers/dma/mediatek/mtk-uart-apdma.c
> 
[...]
> +
> +static int mtk_uart_apdma_probe(struct platform_device *pdev)
> +{
> +	struct device_node *np = pdev->dev.of_node;
> +	struct mtk_uart_apdmadev *mtkd;
> +	struct resource *res;
> +	struct mtk_chan *c;
> +	int bit_mask = 32, rc;
> +	unsigned int i;
> +
> +	mtkd = devm_kzalloc(&pdev->dev, sizeof(*mtkd), GFP_KERNEL);
> +	if (!mtkd)
> +		return -ENOMEM;
> +
> +	mtkd->clk = devm_clk_get(&pdev->dev, NULL);
> +	if (IS_ERR(mtkd->clk)) {
> +		dev_err(&pdev->dev, "No clock specified\n");
> +		rc = PTR_ERR(mtkd->clk);
> +		return rc;
> +	}
> +
> +	if (of_property_read_bool(np, "dma-33bits"))
> +		mtkd->support_33bits = true;

dma-33bits not defined in the binding description.

> +
> +	if (mtkd->support_33bits)
> +		bit_mask = 33;
> +
> +	rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(bit_mask));
> +	if (rc)
> +		return rc;
> +
> +	dma_cap_set(DMA_SLAVE, mtkd->ddev.cap_mask);
> +	mtkd->ddev.device_alloc_chan_resources =
> +				mtk_uart_apdma_alloc_chan_resources;
> +	mtkd->ddev.device_free_chan_resources =
> +				mtk_uart_apdma_free_chan_resources;
> +	mtkd->ddev.device_tx_status = mtk_uart_apdma_tx_status;
> +	mtkd->ddev.device_issue_pending = mtk_uart_apdma_issue_pending;
> +	mtkd->ddev.device_prep_slave_sg = mtk_uart_apdma_prep_slave_sg;
> +	mtkd->ddev.device_config = mtk_uart_apdma_slave_config;
> +	mtkd->ddev.device_pause = mtk_uart_apdma_device_pause;
> +	mtkd->ddev.device_terminate_all = mtk_uart_apdma_terminate_all;
> +	mtkd->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE);
> +	mtkd->ddev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE);
> +	mtkd->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
> +	mtkd->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
> +	mtkd->ddev.dev = &pdev->dev;
> +	INIT_LIST_HEAD(&mtkd->ddev.channels);
> +
> +	mtkd->dma_requests = MTK_UART_APDMA_NR_VCHANS;

Do this if dma-requests property is not present.

> +	if (of_property_read_u32(np, "dma-requests", &mtkd->dma_requests)) {

It's quite obvious what this does, but IMHO it should be reflected in the binding.

Regards,
Matthias

> +		dev_info(&pdev->dev,
> +			 "Using %u as missing dma-requests property\n",
> +			 MTK_UART_APDMA_NR_VCHANS);
> +	}
> +
> +	mtkd->dma_irq = devm_kcalloc(&pdev->dev, mtkd->dma_requests,
> +				 sizeof(*mtkd->dma_irq), GFP_KERNEL);
> +	if (!mtkd->dma_irq)
> +		return -ENOMEM;
> +
> +	for (i = 0; i < mtkd->dma_requests; i++) {
> +		c = devm_kzalloc(mtkd->ddev.dev, sizeof(*c), GFP_KERNEL);
> +		if (!c) {
> +			rc = -ENODEV;
> +			goto err_no_dma;
> +		}
> +
> +		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
> +		if (!res) {
> +			rc = -ENODEV;
> +			goto err_no_dma;
> +		}
> +
> +		c->base = devm_ioremap_resource(&pdev->dev, res);
> +		if (IS_ERR(c->base)) {
> +			rc = PTR_ERR(c->base);
> +			goto err_no_dma;
> +		}
> +		c->requested = false;
> +		c->vc.desc_free = mtk_uart_apdma_desc_free;
> +		vchan_init(&c->vc, &mtkd->ddev);
> +
> +		mtkd->dma_irq[i] = platform_get_irq(pdev, i);
> +		if ((int)mtkd->dma_irq[i] < 0) {
> +			dev_err(&pdev->dev, "failed to get IRQ[%d]\n", i);
> +			rc = -EINVAL;
> +			goto err_no_dma;
> +		}
> +	}
> +
> +	pm_runtime_enable(&pdev->dev);
> +	pm_runtime_set_active(&pdev->dev);
> +
> +	rc = dma_async_device_register(&mtkd->ddev);
> +	if (rc)
> +		goto rpm_disable;
> +
> +	platform_set_drvdata(pdev, mtkd);
> +
> +	/* Device-tree DMA controller registration */
> +	rc = of_dma_controller_register(np, of_dma_xlate_by_chan_id, mtkd);
> +	if (rc)
> +		goto dma_remove;
> +
> +	return rc;
> +
> +dma_remove:
> +	dma_async_device_unregister(&mtkd->ddev);
> +rpm_disable:
> +	pm_runtime_disable(&pdev->dev);
> +err_no_dma:
> +	mtk_uart_apdma_free(mtkd);
> +	return rc;
> +}
> +
> +static int mtk_uart_apdma_remove(struct platform_device *pdev)
> +{
> +	struct mtk_uart_apdmadev *mtkd = platform_get_drvdata(pdev);
> +
> +	if (pdev->dev.of_node)
> +		of_dma_controller_free(pdev->dev.of_node);
> +
> +	pm_runtime_disable(&pdev->dev);
> +	pm_runtime_put_noidle(&pdev->dev);
> +
> +	dma_async_device_unregister(&mtkd->ddev);
> +	mtk_uart_apdma_free(mtkd);
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int mtk_uart_apdma_suspend(struct device *dev)
> +{
> +	struct mtk_uart_apdmadev *mtkd = dev_get_drvdata(dev);
> +
> +	if (!pm_runtime_suspended(dev))
> +		clk_disable_unprepare(mtkd->clk);
> +
> +	return 0;
> +}
> +
> +static int mtk_uart_apdma_resume(struct device *dev)
> +{
> +	int ret;
> +	struct mtk_uart_apdmadev *mtkd = dev_get_drvdata(dev);
> +
> +	if (!pm_runtime_suspended(dev)) {
> +		ret = clk_prepare_enable(mtkd->clk);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +#endif /* CONFIG_PM_SLEEP */
> +
> +#ifdef CONFIG_PM
> +static int mtk_uart_apdma_runtime_suspend(struct device *dev)
> +{
> +	struct mtk_uart_apdmadev *mtkd = dev_get_drvdata(dev);
> +
> +	clk_disable_unprepare(mtkd->clk);
> +
> +	return 0;
> +}
> +
> +static int mtk_uart_apdma_runtime_resume(struct device *dev)
> +{
> +	int ret;
> +	struct mtk_uart_apdmadev *mtkd = dev_get_drvdata(dev);
> +
> +	ret = clk_prepare_enable(mtkd->clk);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> +#endif /* CONFIG_PM */
> +
> +static const struct dev_pm_ops mtk_uart_apdma_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(mtk_uart_apdma_suspend, mtk_uart_apdma_resume)
> +	SET_RUNTIME_PM_OPS(mtk_uart_apdma_runtime_suspend,
> +			   mtk_uart_apdma_runtime_resume, NULL)
> +};
> +
> +static struct platform_driver mtk_uart_apdma_driver = {
> +	.probe	= mtk_uart_apdma_probe,
> +	.remove	= mtk_uart_apdma_remove,
> +	.driver = {
> +		.name		= KBUILD_MODNAME,
> +		.pm		= &mtk_uart_apdma_pm_ops,
> +		.of_match_table = of_match_ptr(mtk_uart_apdma_match),
> +	},
> +};
> +
> +module_platform_driver(mtk_uart_apdma_driver);
> +
> +MODULE_DESCRIPTION("MediaTek UART APDMA Controller Driver");
> +MODULE_AUTHOR("Long Cheng <long.cheng@mediatek.com>");
> +MODULE_LICENSE("GPL v2");
> +
>

^ permalink raw reply

* [v2,1/1] dt-bindings: dmaengine: Add MediaTek Command-Queue DMA controller bindings
From: Matthias Brugger @ 2019-02-14  9:19 UTC (permalink / raw)
  To: shun-chih.yu, Sean Wang, Vinod Koul, Rob Herring, Dan Williams
  Cc: dmaengine, linux-arm-kernel, linux-mediatek, devicetree,
	linux-kernel, srv_wsdupstream

On 14/02/2019 08:54, shun-chih.yu@mediatek.com wrote:
> From: Shun-Chih Yu <shun-chih.yu@mediatek.com>
> 
> Document the devicetree bindings for MediaTek Command-Queue DMA controller
> which could be found on MT6765 SoC or other similar Mediatek SoCs.
> 
> Signed-off-by: Shun-Chih Yu <shun-chih.yu@mediatek.com>
> Reviewed-by: Rob Herring <robh@kernel.org>
> Acked-by: Sean Wang <sean.wang@kernel.org>
> ---
>  .../devicetree/bindings/dma/mtk-cqdma.txt          |   31 ++++++++++++++++++++
>  1 file changed, 31 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/dma/mtk-cqdma.txt
> 
> diff --git a/Documentation/devicetree/bindings/dma/mtk-cqdma.txt b/Documentation/devicetree/bindings/dma/mtk-cqdma.txt
> new file mode 100644
> index 0000000..fb12927
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/dma/mtk-cqdma.txt
> @@ -0,0 +1,31 @@
> +MediaTek Command-Queue DMA Controller
> +==================================
> +
> +Required properties:
> +
> +- compatible:	Must be "mediatek,mt6765-cqdma" for MT6765.
> +- reg:		Should contain the base address and length for each channel.
> +- interrupts:	Should contain references to the interrupts for each channel.
> +- clocks:	Should be the clock specifiers corresponding to the entry in
> +		clock-names property.
> +- clock-names:	Should contain "cqdma" entries.

entries -> entry. There is only one clock

> +- dma-channels: The number of DMA channels supported by the controller.
> +- dma-requests: The number of DMA request supported by the controller.

The driver handles these as optional and uses MTK_CQDMA_NR_VCHANS and
MTK_CQDMA_NR_PCHANS in case the property is not present.

> +- #dma-cells: 	The length of the DMA specifier, must be <1>. This one cell
> +		in dmas property of a client device represents the channel
> +		number.
> +Example:
> +
> +        cqdma: dma-controller@10212000 {
> +		compatible = "mediatek,mt6765-cqdma";
> +		reg = <0 0x10212000 0 0x1000>;

Does this mean that you have to resources at base = 0x0 with different length?

For the next time, please send driver and binding description in one series (two
patches). That makes things easier to review.

Thanks,
Matthias

> +		interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_LOW>,
> +			<GIC_SPI 114 IRQ_TYPE_LEVEL_LOW>;
> +		clocks = <&infracfg CLK_IFR_CQ_DMA>;
> +		clock-names = "cqdma";
> +		dma-channels = <2>;
> +		dma-requests = <32>;
> +		#dma-cells = <1>;
> +	};
> +
> +DMA clients must use the format described in dma/dma.txt file.
>

^ permalink raw reply

* [v2,1/1] dt-bindings: dmaengine: Add MediaTek Command-Queue DMA controller bindings
From: Matthias Brugger @ 2019-02-14  9:18 UTC (permalink / raw)
  To: shun-chih.yu, Sean Wang, Vinod Koul, Rob Herring, Dan Williams
  Cc: dmaengine, linux-arm-kernel, linux-mediatek, devicetree,
	linux-kernel, srv_wsdupstream

On 14/02/2019 08:54, shun-chih.yu@mediatek.com wrote:
> From: Shun-Chih Yu <shun-chih.yu@mediatek.com>
> 
> Document the devicetree bindings for MediaTek Command-Queue DMA controller
> which could be found on MT6765 SoC or other similar Mediatek SoCs.
> 
> Signed-off-by: Shun-Chih Yu <shun-chih.yu@mediatek.com>
> Reviewed-by: Rob Herring <robh@kernel.org>
> Acked-by: Sean Wang <sean.wang@kernel.org>
> ---
>  .../devicetree/bindings/dma/mtk-cqdma.txt          |   31 ++++++++++++++++++++
>  1 file changed, 31 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/dma/mtk-cqdma.txt
> 
> diff --git a/Documentation/devicetree/bindings/dma/mtk-cqdma.txt b/Documentation/devicetree/bindings/dma/mtk-cqdma.txt
> new file mode 100644
> index 0000000..fb12927
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/dma/mtk-cqdma.txt
> @@ -0,0 +1,31 @@
> +MediaTek Command-Queue DMA Controller
> +==================================
> +
> +Required properties:
> +
> +- compatible:	Must be "mediatek,mt6765-cqdma" for MT6765.
> +- reg:		Should contain the base address and length for each channel.
> +- interrupts:	Should contain references to the interrupts for each channel.
> +- clocks:	Should be the clock specifiers corresponding to the entry in
> +		clock-names property.
> +- clock-names:	Should contain "cqdma" entries.

entries -> entry. There is only one clock

> +- dma-channels: The number of DMA channels supported by the controller.
> +- dma-requests: The number of DMA request supported by the controller.

The driver handles these as optional and uses MTK_CQDMA_NR_VCHANS and
MTK_CQDMA_NR_PCHANS in case the property is not present.

> +- #dma-cells: 	The length of the DMA specifier, must be <1>. This one cell
> +		in dmas property of a client device represents the channel
> +		number.
> +Example:
> +
> +        cqdma: dma-controller@10212000 {
> +		compatible = "mediatek,mt6765-cqdma";
> +		reg = <0 0x10212000 0 0x1000>;

Does this mean that you have to resources at base = 0x0 with different length?

Regards,
Matthias

> +		interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_LOW>,
> +			<GIC_SPI 114 IRQ_TYPE_LEVEL_LOW>;
> +		clocks = <&infracfg CLK_IFR_CQ_DMA>;
> +		clock-names = "cqdma";
> +		dma-channels = <2>;
> +		dma-requests = <32>;
> +		#dma-cells = <1>;
> +	};
> +
> +DMA clients must use the format described in dma/dma.txt file.
>

^ permalink raw reply

* [v2,1/1] dt-bindings: dmaengine: Add MediaTek Command-Queue DMA controller bindings
From: Matthias Brugger @ 2019-02-14  9:04 UTC (permalink / raw)
  To: shun-chih.yu, Sean Wang, Vinod Koul, Rob Herring, Dan Williams
  Cc: dmaengine, linux-arm-kernel, linux-mediatek, devicetree,
	linux-kernel, srv_wsdupstream

On 14/02/2019 08:54, shun-chih.yu@mediatek.com wrote:
> From: Shun-Chih Yu <shun-chih.yu@mediatek.com>
> 
> Document the devicetree bindings for MediaTek Command-Queue DMA controller
> which could be found on MT6765 SoC or other similar Mediatek SoCs.
> 
> Signed-off-by: Shun-Chih Yu <shun-chih.yu@mediatek.com>
> Reviewed-by: Rob Herring <robh@kernel.org>
> Acked-by: Sean Wang <sean.wang@kernel.org>
> ---

Please don't send cover letters for single patches, just for series.
If you want to add some information to a single patch, which should not show up
in the commit message (e.g. change log) you can do that below the "---"

Regards,
Matthias

>  .../devicetree/bindings/dma/mtk-cqdma.txt          |   31 ++++++++++++++++++++
>  1 file changed, 31 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/dma/mtk-cqdma.txt
> 
> diff --git a/Documentation/devicetree/bindings/dma/mtk-cqdma.txt b/Documentation/devicetree/bindings/dma/mtk-cqdma.txt
> new file mode 100644
> index 0000000..fb12927
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/dma/mtk-cqdma.txt
> @@ -0,0 +1,31 @@
> +MediaTek Command-Queue DMA Controller
> +==================================
> +
> +Required properties:
> +
> +- compatible:	Must be "mediatek,mt6765-cqdma" for MT6765.
> +- reg:		Should contain the base address and length for each channel.
> +- interrupts:	Should contain references to the interrupts for each channel.
> +- clocks:	Should be the clock specifiers corresponding to the entry in
> +		clock-names property.
> +- clock-names:	Should contain "cqdma" entries.
> +- dma-channels: The number of DMA channels supported by the controller.
> +- dma-requests: The number of DMA request supported by the controller.
> +- #dma-cells: 	The length of the DMA specifier, must be <1>. This one cell
> +		in dmas property of a client device represents the channel
> +		number.
> +Example:
> +
> +        cqdma: dma-controller@10212000 {
> +		compatible = "mediatek,mt6765-cqdma";
> +		reg = <0 0x10212000 0 0x1000>;
> +		interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_LOW>,
> +			<GIC_SPI 114 IRQ_TYPE_LEVEL_LOW>;
> +		clocks = <&infracfg CLK_IFR_CQ_DMA>;
> +		clock-names = "cqdma";
> +		dma-channels = <2>;
> +		dma-requests = <32>;
> +		#dma-cells = <1>;
> +	};
> +
> +DMA clients must use the format described in dma/dma.txt file.
>

^ permalink raw reply

* [v2,1/1] dt-bindings: dmaengine: Add MediaTek Command-Queue DMA controller bindings
From: shun-chih.yu @ 2019-02-14  7:54 UTC (permalink / raw)
  To: Sean Wang, Vinod Koul, Rob Herring, Matthias Brugger,
	Dan Williams
  Cc: dmaengine, linux-arm-kernel, linux-mediatek, devicetree,
	linux-kernel, srv_wsdupstream, Shun-Chih Yu

From: Shun-Chih Yu <shun-chih.yu@mediatek.com>

Document the devicetree bindings for MediaTek Command-Queue DMA controller
which could be found on MT6765 SoC or other similar Mediatek SoCs.

Signed-off-by: Shun-Chih Yu <shun-chih.yu@mediatek.com>
Reviewed-by: Rob Herring <robh@kernel.org>
Acked-by: Sean Wang <sean.wang@kernel.org>
---
 .../devicetree/bindings/dma/mtk-cqdma.txt          |   31 ++++++++++++++++++++
 1 file changed, 31 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/dma/mtk-cqdma.txt

diff --git a/Documentation/devicetree/bindings/dma/mtk-cqdma.txt b/Documentation/devicetree/bindings/dma/mtk-cqdma.txt
new file mode 100644
index 0000000..fb12927
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/mtk-cqdma.txt
@@ -0,0 +1,31 @@
+MediaTek Command-Queue DMA Controller
+==================================
+
+Required properties:
+
+- compatible:	Must be "mediatek,mt6765-cqdma" for MT6765.
+- reg:		Should contain the base address and length for each channel.
+- interrupts:	Should contain references to the interrupts for each channel.
+- clocks:	Should be the clock specifiers corresponding to the entry in
+		clock-names property.
+- clock-names:	Should contain "cqdma" entries.
+- dma-channels: The number of DMA channels supported by the controller.
+- dma-requests: The number of DMA request supported by the controller.
+- #dma-cells: 	The length of the DMA specifier, must be <1>. This one cell
+		in dmas property of a client device represents the channel
+		number.
+Example:
+
+        cqdma: dma-controller@10212000 {
+		compatible = "mediatek,mt6765-cqdma";
+		reg = <0 0x10212000 0 0x1000>;
+		interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_LOW>,
+			<GIC_SPI 114 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&infracfg CLK_IFR_CQ_DMA>;
+		clock-names = "cqdma";
+		dma-channels = <2>;
+		dma-requests = <32>;
+		#dma-cells = <1>;
+	};
+
+DMA clients must use the format described in dma/dma.txt file.

^ permalink raw reply related

* [1/1] dt-bindings: dmaengine: Add MediaTek Command-Queue DMA controller bindings
From: shun-chih.yu @ 2019-02-14  7:40 UTC (permalink / raw)
  To: Sean Wang, Vinod Koul, Rob Herring, Matthias Brugger,
	Dan Williams
  Cc: dmaengine, linux-arm-kernel, linux-mediatek, devicetree,
	linux-kernel, srv_wsdupstream, Shun-Chih Yu

From: Shun-Chih Yu <shun-chih.yu@mediatek.com>

Document the devicetree bindings for MediaTek Command-Queue DMA controller
which could be found on MT6765 SoC or other similar Mediatek SoCs.

Change-Id: I9736c8cac9be160358feeab935fabaffc5730519
Signed-off-by: Shun-Chih Yu <shun-chih.yu@mediatek.com>
---
 .../devicetree/bindings/dma/mtk-cqdma.txt          |   31 ++++++++++++++++++++
 1 file changed, 31 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/dma/mtk-cqdma.txt

diff --git a/Documentation/devicetree/bindings/dma/mtk-cqdma.txt b/Documentation/devicetree/bindings/dma/mtk-cqdma.txt
new file mode 100644
index 0000000..fb12927
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/mtk-cqdma.txt
@@ -0,0 +1,31 @@
+MediaTek Command-Queue DMA Controller
+==================================
+
+Required properties:
+
+- compatible:	Must be "mediatek,mt6765-cqdma" for MT6765.
+- reg:		Should contain the base address and length for each channel.
+- interrupts:	Should contain references to the interrupts for each channel.
+- clocks:	Should be the clock specifiers corresponding to the entry in
+		clock-names property.
+- clock-names:	Should contain "cqdma" entries.
+- dma-channels: The number of DMA channels supported by the controller.
+- dma-requests: The number of DMA request supported by the controller.
+- #dma-cells: 	The length of the DMA specifier, must be <1>. This one cell
+		in dmas property of a client device represents the channel
+		number.
+Example:
+
+        cqdma: dma-controller@10212000 {
+		compatible = "mediatek,mt6765-cqdma";
+		reg = <0 0x10212000 0 0x1000>;
+		interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_LOW>,
+			<GIC_SPI 114 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&infracfg CLK_IFR_CQ_DMA>;
+		clock-names = "cqdma";
+		dma-channels = <2>;
+		dma-requests = <32>;
+		#dma-cells = <1>;
+	};
+
+DMA clients must use the format described in dma/dma.txt file.

^ permalink raw reply related

* [v10,1/3] dmaengine: 8250_mtk_dma: add MediaTek uart DMA support
From: Long Cheng @ 2019-02-14  2:44 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Randy Dunlap, Rob Herring, Mark Rutland, Ryder Lee, Sean Wang,
	Nicolas Boichat, Matthias Brugger, Dan Williams,
	Greg Kroah-Hartman, Jiri Slaby, Sean Wang, dmaengine, devicetree,
	linux-arm-kernel, linux-mediatek, linux-kernel, linux-serial,
	srv_heupstream, Yingjoe Chen, YT Shen, Zhenbao Liu, Long Cheng

On Mon, 2019-02-04 at 12:51 +0530, Vinod Koul wrote:

Hi Vinod sir,

> On 18-01-19, 11:10, Long Cheng wrote:
> > +static enum dma_status mtk_uart_apdma_tx_status(struct dma_chan *chan,
> > +					 dma_cookie_t cookie,
> > +					 struct dma_tx_state *txstate)
> > +{
> > +	struct mtk_chan *c = to_mtk_uart_apdma_chan(chan);
> > +	enum dma_status ret;
> > +	unsigned long flags;
> > +
> > +	if (!txstate)
> > +		return DMA_ERROR;
> 
> Why, it is not a mandatory arg!

Next version, I will remove it.
> 
> > +	ret = dma_cookie_status(chan, cookie, txstate);
> > +	spin_lock_irqsave(&c->vc.lock, flags);
> > +	if (ret == DMA_IN_PROGRESS) {
> > +		c->rx_status = mtk_uart_apdma_read(c, VFF_RPT) & VFF_RING_SIZE;
> > +		dma_set_residue(txstate, c->rx_status);
> > +	} else if (ret == DMA_COMPLETE && c->dir == DMA_DEV_TO_MEM) {
> > +		dma_set_residue(txstate, c->rx_status);
> 
> what is the point is setting residue to comleted txn, it is zero!
> 
> > +	} else {
> > +		dma_set_residue(txstate, 0);
> 
> naah that doesnt sound correct!
> 
Next version, I will modify the function.

> > +static void mtk_uart_apdma_config_write(struct dma_chan *chan,
> > +			       struct dma_slave_config *cfg,
> > +			       enum dma_transfer_direction dir)
> > +{
> > +	struct mtk_chan *c = to_mtk_uart_apdma_chan(chan);
> > +	struct mtk_uart_apdmadev *mtkd =
> > +				to_mtk_uart_apdma_dev(c->vc.chan.device);
> > +	unsigned int tmp;
> > +
> > +	if (mtk_uart_apdma_read(c, VFF_EN) == VFF_EN_B)
> > +		return;
> > +
> > +	c->dir = dir;
> > +
> > +	if (dir == DMA_DEV_TO_MEM) {
> > +		tmp = cfg->src_addr_width * 1024;
> 
> why multiply by 1024?
> 
Next version, I will modify the this, with 'src_port_window_size' &&
'dst_port_window_size'.

> > +static int mtk_uart_apdma_device_pause(struct dma_chan *chan)
> > +{
> > +	/* just for check caps pass */
> > +	return 0;
> > +}
> 
> please remove, this is not a mandatory fn

Can't remove it. Before the mail, i had explained it. in 8250 uart
framework, will check the function..

thanks.

^ permalink raw reply

* [01/18] MIPS: lantiq: pass struct device to DMA API functions
From: Paul Burton @ 2019-02-12 17:41 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: John Crispin, Vinod Koul, Dmitry Tarnyagin, Nicolas Ferre,
	Sudip Mukherjee, Felipe Balbi, linux-mips@vger.kernel.org,
	linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org,
	netdev@vger.kernel.org, linux-usb@vger.kernel.org,
	linux-fbdev@vger.kernel.org, alsa-devel@alsa-project.org,
	iommu@lists.linux-foundation.org

Hello,

Christoph Hellwig wrote:
> The DMA API generally relies on a struct device to work properly, and
> only barely works without one for legacy reasons.  Pass the easily
> available struct device from the platform_device to remedy this.
> 
> Also use GFP_KERNEL instead of GFP_ATOMIC as the gfp_t for the memory
> allocation, as we aren't in interrupt context or under a lock.
> 
> Note that this whole function looks somewhat bogus given that we never
> even look at the returned dma address, and the CPHYSADDR magic on
> a returned noncached mapping looks "interesting".  But I'll leave
> that to people more familiar with the code to sort out.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>

Applied to mips-fixes.

Thanks,
    Paul

[ This message was auto-generated; if you believe anything is incorrect
  then please email paul.burton@mips.com to report it. ]

^ permalink raw reply

* [V2,3/3] dmaengine: dmatest: move test data alloc & free into functions
From: Alexandru Ardelean @ 2019-02-12 15:11 UTC (permalink / raw)
  To: dmaengine, vkoul; +Cc: Alexandru Ardelean

This patch starts to take advantage of the `dmatest_data` struct by moving
the common allocation & free-ing bits into functions.

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/dma/dmatest.c | 110 +++++++++++++++++++++---------------------
 1 file changed, 55 insertions(+), 55 deletions(-)

diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index 3b148c2647f8..50221d467d86 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -486,6 +486,53 @@ static unsigned long long dmatest_KBs(s64 runtime, unsigned long long len)
 	return FIXPT_TO_INT(dmatest_persec(runtime, len >> 10));
 }
 
+static void __dmatest_free_test_data(struct dmatest_data *d, unsigned int cnt)
+{
+	unsigned int i;
+
+	for (i = 0; i < cnt; i++)
+		kfree(d->raw[i]);
+
+	kfree(d->aligned);
+	kfree(d->raw);
+}
+
+static void dmatest_free_test_data(struct dmatest_data *d)
+{
+	__dmatest_free_test_data(d, d->cnt);
+}
+
+static int dmatest_alloc_test_data(struct dmatest_data *d,
+		unsigned int buf_size, u8 align)
+{
+	unsigned int i = 0;
+
+	d->raw = kcalloc(d->cnt + 1, sizeof(u8 *), GFP_KERNEL);
+	if (!d->raw)
+		return -ENOMEM;
+
+	d->aligned = kcalloc(d->cnt + 1, sizeof(u8 *), GFP_KERNEL);
+	if (!d->aligned)
+		goto err;
+
+	for (i = 0; i < d->cnt; i++) {
+		d->raw[i] = kmalloc(buf_size + align, GFP_KERNEL);
+		if (!d->raw[i])
+			goto err;
+
+		/* align to alignment restriction */
+		if (align)
+			d->aligned[i] = PTR_ALIGN(d->raw[i], align);
+		else
+			d->aligned[i] = d->raw[i];
+	}
+
+	return 0;
+err:
+	__dmatest_free_test_data(d, i);
+	return -ENOMEM;
+}
+
 /*
  * This function repeatedly tests DMA transfers of various lengths and
  * offsets for a given operation type until it is told to exit by
@@ -588,55 +635,17 @@ static int dmatest_func(void *data)
 		goto err_free_coefs;
 	}
 
-	src->aligned = kcalloc(src->cnt + 1, sizeof(u8 *), GFP_KERNEL);
-	if (!src->aligned)
+	if (dmatest_alloc_test_data(src, buf_size, align) < 0)
 		goto err_free_coefs;
 
-	src->raw = kcalloc(src->cnt + 1, sizeof(u8 *), GFP_KERNEL);
-	if (!src->raw)
-		goto err_usrcs;
-
-	for (i = 0; i < src->cnt; i++) {
-		src->raw[i] = kmalloc(buf_size + align,
-					   GFP_KERNEL);
-		if (!src->raw[i])
-			goto err_srcbuf;
-
-		/* align srcs to alignment restriction */
-		if (align)
-			src->aligned[i] = PTR_ALIGN(src->raw[i], align);
-		else
-			src->aligned[i] = src->raw[i];
-	}
-	src->aligned[i] = NULL;
-
-	dst->aligned = kcalloc(dst->cnt + 1, sizeof(u8 *), GFP_KERNEL);
-	if (!dst->aligned)
-		goto err_dsts;
-
-	dst->raw = kcalloc(dst->cnt + 1, sizeof(u8 *), GFP_KERNEL);
-	if (!dst->raw)
-		goto err_udsts;
-
-	for (i = 0; i < dst->cnt; i++) {
-		dst->raw[i] = kmalloc(buf_size + align,
-					   GFP_KERNEL);
-		if (!dst->raw[i])
-			goto err_dstbuf;
-
-		/* align dsts to alignment restriction */
-		if (align)
-			dst->aligned[i] = PTR_ALIGN(dst->raw[i], align);
-		else
-			dst->aligned[i] = dst->raw[i];
-	}
-	dst->aligned[i] = NULL;
+	if (dmatest_alloc_test_data(dst, buf_size, align) < 0)
+		goto err_src;
 
 	set_user_nice(current, 10);
 
 	srcs = kcalloc(src->cnt, sizeof(dma_addr_t), GFP_KERNEL);
 	if (!srcs)
-		goto err_dstbuf;
+		goto err_dst;
 
 	dma_pq = kcalloc(dst->cnt, sizeof(dma_addr_t), GFP_KERNEL);
 	if (!dma_pq)
@@ -865,19 +874,10 @@ static int dmatest_func(void *data)
 	kfree(dma_pq);
 err_srcs_array:
 	kfree(srcs);
-err_dstbuf:
-	for (i = 0; dst->raw[i]; i++)
-		kfree(dst->raw[i]);
-	kfree(dst->raw);
-err_udsts:
-	kfree(dst->aligned);
-err_dsts:
-err_srcbuf:
-	for (i = 0; src->raw[i]; i++)
-		kfree(src->raw[i]);
-	kfree(src->raw);
-err_usrcs:
-	kfree(src->aligned);
+err_dst:
+	dmatest_free_test_data(dst);
+err_src:
+	dmatest_free_test_data(src);
 err_free_coefs:
 	kfree(pq_coefs);
 err_thread_type:

^ permalink raw reply related

* [V2,2/3] dmaengine: dmatest: add short-hand `buf_size` var in dmatest_func()
From: Alexandru Ardelean @ 2019-02-12 15:11 UTC (permalink / raw)
  To: dmaengine, vkoul; +Cc: Alexandru Ardelean

This is just a cosmetic change, since this variable gets used quite a bit
inside the dmatest_func() routine.

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/dma/dmatest.c | 32 +++++++++++++++++---------------
 1 file changed, 17 insertions(+), 15 deletions(-)

diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index ea1f885e70f4..3b148c2647f8 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -516,6 +516,7 @@ static int dmatest_func(void *data)
 	enum dma_ctrl_flags 	flags;
 	u8			*pq_coefs = NULL;
 	int			ret;
+	unsigned int 		buf_size;
 	struct dmatest_data	*src;
 	struct dmatest_data	*dst;
 	int			i;
@@ -580,9 +581,10 @@ static int dmatest_func(void *data)
 		goto err_free_coefs;
 	}
 
-	if (1 << align > params->buf_size) {
+	buf_size = params->buf_size;
+	if (1 << align > buf_size) {
 		pr_err("%u-byte buffer too small for %d-byte alignment\n",
-		       params->buf_size, 1 << align);
+		       buf_size, 1 << align);
 		goto err_free_coefs;
 	}
 
@@ -595,7 +597,7 @@ static int dmatest_func(void *data)
 		goto err_usrcs;
 
 	for (i = 0; i < src->cnt; i++) {
-		src->raw[i] = kmalloc(params->buf_size + align,
+		src->raw[i] = kmalloc(buf_size + align,
 					   GFP_KERNEL);
 		if (!src->raw[i])
 			goto err_srcbuf;
@@ -617,7 +619,7 @@ static int dmatest_func(void *data)
 		goto err_udsts;
 
 	for (i = 0; i < dst->cnt; i++) {
-		dst->raw[i] = kmalloc(params->buf_size + align,
+		dst->raw[i] = kmalloc(buf_size + align,
 					   GFP_KERNEL);
 		if (!dst->raw[i])
 			goto err_dstbuf;
@@ -656,16 +658,16 @@ static int dmatest_func(void *data)
 		total_tests++;
 
 		if (params->transfer_size) {
-			if (params->transfer_size >= params->buf_size) {
+			if (params->transfer_size >= buf_size) {
 				pr_err("%u-byte transfer size must be lower than %u-buffer size\n",
-				       params->transfer_size, params->buf_size);
+				       params->transfer_size, buf_size);
 				break;
 			}
 			len = params->transfer_size;
 		} else if (params->norandom) {
-			len = params->buf_size;
+			len = buf_size;
 		} else {
-			len = dmatest_random() % params->buf_size + 1;
+			len = dmatest_random() % buf_size + 1;
 		}
 
 		/* Do not alter transfer size explicitly defined by user */
@@ -680,8 +682,8 @@ static int dmatest_func(void *data)
 			src->off = 0;
 			dst->off = 0;
 		} else {
-			src->off = dmatest_random() % (params->buf_size - len + 1);
-			dst->off = dmatest_random() % (params->buf_size - len + 1);
+			src->off = dmatest_random() % (buf_size - len + 1);
+			dst->off = dmatest_random() % (buf_size - len + 1);
 
 			src->off = (src->off >> align) << align;
 			dst->off = (dst->off >> align) << align;
@@ -690,9 +692,9 @@ static int dmatest_func(void *data)
 		if (!params->noverify) {
 			start = ktime_get();
 			dmatest_init_srcs(src->aligned, src->off, len,
-					  params->buf_size, is_memset);
+					  buf_size, is_memset);
 			dmatest_init_dsts(dst->aligned, dst->off, len,
-					  params->buf_size, is_memset);
+					  buf_size, is_memset);
 
 			diff = ktime_sub(ktime_get(), start);
 			filltime = ktime_add(filltime, diff);
@@ -707,7 +709,7 @@ static int dmatest_func(void *data)
 			continue;
 		}
 
-		um->len = params->buf_size;
+		um->len = buf_size;
 		for (i = 0; i < src->cnt; i++) {
 			void *buf = src->aligned[i];
 			struct page *pg = virt_to_page(buf);
@@ -827,7 +829,7 @@ static int dmatest_func(void *data)
 				src->off + len, src->off,
 				PATTERN_SRC | PATTERN_COPY, true, is_memset);
 		error_count += dmatest_verify(src->aligned, src->off + len,
-				params->buf_size, src->off + len,
+				buf_size, src->off + len,
 				PATTERN_SRC, true, is_memset);
 
 		pr_debug("%s: verifying dest buffer...\n", current->comm);
@@ -839,7 +841,7 @@ static int dmatest_func(void *data)
 				PATTERN_SRC | PATTERN_COPY, false, is_memset);
 
 		error_count += dmatest_verify(dst->aligned, dst->off + len,
-				params->buf_size, dst->off + len,
+				buf_size, dst->off + len,
 				PATTERN_DST, false, is_memset);
 
 		diff = ktime_sub(ktime_get(), start);

^ permalink raw reply related

* [V2,1/3] dmaengine: dmatest: wrap src & dst data into a struct
From: Alexandru Ardelean @ 2019-02-12 15:11 UTC (permalink / raw)
  To: dmaengine, vkoul; +Cc: Alexandru Ardelean

This change wraps the data for the source & destination buffers into a
`struct dmatest_data`. The rename patterns are:
 * src_cnt -> src->cnt
 * dst_cnt -> dst->cnt
 * src_off -> src->off
 * dst_off -> dst->off
 * thread->srcs -> src->aligned
 * thread->usrcs -> src->raw
 * thread->dsts -> dst->aligned
 * thread->udsts -> dst->raw

The intent is to make a function that moves duplicate parts of the code
into common alloc & free functions, which will unclutter the
`dmatest_func()` function.

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---

Changelog v1 -> v2:
* split original `[PATCH] dmaengine: dmatest: wrap src & dst data into a
  struct` into 3 smaller patches

 drivers/dma/dmatest.c | 195 ++++++++++++++++++++++--------------------
 1 file changed, 101 insertions(+), 94 deletions(-)

diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index 2eea4ef72915..ea1f885e70f4 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -200,15 +200,20 @@ struct dmatest_done {
 	wait_queue_head_t	*wait;
 };
 
+struct dmatest_data {
+	u8		**raw;
+	u8		**aligned;
+	unsigned int	cnt;
+	unsigned int	off;
+};
+
 struct dmatest_thread {
 	struct list_head	node;
 	struct dmatest_info	*info;
 	struct task_struct	*task;
 	struct dma_chan		*chan;
-	u8			**srcs;
-	u8			**usrcs;
-	u8			**dsts;
-	u8			**udsts;
+	struct dmatest_data	src;
+	struct dmatest_data	dst;
 	enum dma_transaction_type type;
 	wait_queue_head_t done_wait;
 	struct dmatest_done test_done;
@@ -511,8 +516,8 @@ static int dmatest_func(void *data)
 	enum dma_ctrl_flags 	flags;
 	u8			*pq_coefs = NULL;
 	int			ret;
-	int			src_cnt;
-	int			dst_cnt;
+	struct dmatest_data	*src;
+	struct dmatest_data	*dst;
 	int			i;
 	ktime_t			ktime, start, diff;
 	ktime_t			filltime = 0;
@@ -535,25 +540,27 @@ static int dmatest_func(void *data)
 	params = &info->params;
 	chan = thread->chan;
 	dev = chan->device;
+	src = &thread->src;
+	dst = &thread->dst;
 	if (thread->type == DMA_MEMCPY) {
 		align = params->alignment < 0 ? dev->copy_align :
 						params->alignment;
-		src_cnt = dst_cnt = 1;
+		src->cnt = dst->cnt = 1;
 	} else if (thread->type == DMA_MEMSET) {
 		align = params->alignment < 0 ? dev->fill_align :
 						params->alignment;
-		src_cnt = dst_cnt = 1;
+		src->cnt = dst->cnt = 1;
 		is_memset = true;
 	} else if (thread->type == DMA_XOR) {
 		/* force odd to ensure dst = src */
-		src_cnt = min_odd(params->xor_sources | 1, dev->max_xor);
-		dst_cnt = 1;
+		src->cnt = min_odd(params->xor_sources | 1, dev->max_xor);
+		dst->cnt = 1;
 		align = params->alignment < 0 ? dev->xor_align :
 						params->alignment;
 	} else if (thread->type == DMA_PQ) {
 		/* force odd to ensure dst = src */
-		src_cnt = min_odd(params->pq_sources | 1, dma_maxpq(dev, 0));
-		dst_cnt = 2;
+		src->cnt = min_odd(params->pq_sources | 1, dma_maxpq(dev, 0));
+		dst->cnt = 2;
 		align = params->alignment < 0 ? dev->pq_align :
 						params->alignment;
 
@@ -561,15 +568,15 @@ static int dmatest_func(void *data)
 		if (!pq_coefs)
 			goto err_thread_type;
 
-		for (i = 0; i < src_cnt; i++)
+		for (i = 0; i < src->cnt; i++)
 			pq_coefs[i] = 1;
 	} else
 		goto err_thread_type;
 
 	/* Check if buffer count fits into map count variable (u8) */
-	if ((src_cnt + dst_cnt) >= 255) {
+	if ((src->cnt + dst->cnt) >= 255) {
 		pr_err("too many buffers (%d of 255 supported)\n",
-		       src_cnt + dst_cnt);
+		       src->cnt + dst->cnt);
 		goto err_free_coefs;
 	}
 
@@ -579,57 +586,57 @@ static int dmatest_func(void *data)
 		goto err_free_coefs;
 	}
 
-	thread->srcs = kcalloc(src_cnt + 1, sizeof(u8 *), GFP_KERNEL);
-	if (!thread->srcs)
+	src->aligned = kcalloc(src->cnt + 1, sizeof(u8 *), GFP_KERNEL);
+	if (!src->aligned)
 		goto err_free_coefs;
 
-	thread->usrcs = kcalloc(src_cnt + 1, sizeof(u8 *), GFP_KERNEL);
-	if (!thread->usrcs)
+	src->raw = kcalloc(src->cnt + 1, sizeof(u8 *), GFP_KERNEL);
+	if (!src->raw)
 		goto err_usrcs;
 
-	for (i = 0; i < src_cnt; i++) {
-		thread->usrcs[i] = kmalloc(params->buf_size + align,
+	for (i = 0; i < src->cnt; i++) {
+		src->raw[i] = kmalloc(params->buf_size + align,
 					   GFP_KERNEL);
-		if (!thread->usrcs[i])
+		if (!src->raw[i])
 			goto err_srcbuf;
 
 		/* align srcs to alignment restriction */
 		if (align)
-			thread->srcs[i] = PTR_ALIGN(thread->usrcs[i], align);
+			src->aligned[i] = PTR_ALIGN(src->raw[i], align);
 		else
-			thread->srcs[i] = thread->usrcs[i];
+			src->aligned[i] = src->raw[i];
 	}
-	thread->srcs[i] = NULL;
+	src->aligned[i] = NULL;
 
-	thread->dsts = kcalloc(dst_cnt + 1, sizeof(u8 *), GFP_KERNEL);
-	if (!thread->dsts)
+	dst->aligned = kcalloc(dst->cnt + 1, sizeof(u8 *), GFP_KERNEL);
+	if (!dst->aligned)
 		goto err_dsts;
 
-	thread->udsts = kcalloc(dst_cnt + 1, sizeof(u8 *), GFP_KERNEL);
-	if (!thread->udsts)
+	dst->raw = kcalloc(dst->cnt + 1, sizeof(u8 *), GFP_KERNEL);
+	if (!dst->raw)
 		goto err_udsts;
 
-	for (i = 0; i < dst_cnt; i++) {
-		thread->udsts[i] = kmalloc(params->buf_size + align,
+	for (i = 0; i < dst->cnt; i++) {
+		dst->raw[i] = kmalloc(params->buf_size + align,
 					   GFP_KERNEL);
-		if (!thread->udsts[i])
+		if (!dst->raw[i])
 			goto err_dstbuf;
 
 		/* align dsts to alignment restriction */
 		if (align)
-			thread->dsts[i] = PTR_ALIGN(thread->udsts[i], align);
+			dst->aligned[i] = PTR_ALIGN(dst->raw[i], align);
 		else
-			thread->dsts[i] = thread->udsts[i];
+			dst->aligned[i] = dst->raw[i];
 	}
-	thread->dsts[i] = NULL;
+	dst->aligned[i] = NULL;
 
 	set_user_nice(current, 10);
 
-	srcs = kcalloc(src_cnt, sizeof(dma_addr_t), GFP_KERNEL);
+	srcs = kcalloc(src->cnt, sizeof(dma_addr_t), GFP_KERNEL);
 	if (!srcs)
 		goto err_dstbuf;
 
-	dma_pq = kcalloc(dst_cnt, sizeof(dma_addr_t), GFP_KERNEL);
+	dma_pq = kcalloc(dst->cnt, sizeof(dma_addr_t), GFP_KERNEL);
 	if (!dma_pq)
 		goto err_srcs_array;
 
@@ -644,7 +651,7 @@ static int dmatest_func(void *data)
 		struct dma_async_tx_descriptor *tx = NULL;
 		struct dmaengine_unmap_data *um;
 		dma_addr_t *dsts;
-		unsigned int src_off, dst_off, len;
+		unsigned int len;
 
 		total_tests++;
 
@@ -670,59 +677,59 @@ static int dmatest_func(void *data)
 		total_len += len;
 
 		if (params->norandom) {
-			src_off = 0;
-			dst_off = 0;
+			src->off = 0;
+			dst->off = 0;
 		} else {
-			src_off = dmatest_random() % (params->buf_size - len + 1);
-			dst_off = dmatest_random() % (params->buf_size - len + 1);
+			src->off = dmatest_random() % (params->buf_size - len + 1);
+			dst->off = dmatest_random() % (params->buf_size - len + 1);
 
-			src_off = (src_off >> align) << align;
-			dst_off = (dst_off >> align) << align;
+			src->off = (src->off >> align) << align;
+			dst->off = (dst->off >> align) << align;
 		}
 
 		if (!params->noverify) {
 			start = ktime_get();
-			dmatest_init_srcs(thread->srcs, src_off, len,
+			dmatest_init_srcs(src->aligned, src->off, len,
 					  params->buf_size, is_memset);
-			dmatest_init_dsts(thread->dsts, dst_off, len,
+			dmatest_init_dsts(dst->aligned, dst->off, len,
 					  params->buf_size, is_memset);
 
 			diff = ktime_sub(ktime_get(), start);
 			filltime = ktime_add(filltime, diff);
 		}
 
-		um = dmaengine_get_unmap_data(dev->dev, src_cnt + dst_cnt,
+		um = dmaengine_get_unmap_data(dev->dev, src->cnt + dst->cnt,
 					      GFP_KERNEL);
 		if (!um) {
 			failed_tests++;
 			result("unmap data NULL", total_tests,
-			       src_off, dst_off, len, ret);
+			       src->off, dst->off, len, ret);
 			continue;
 		}
 
 		um->len = params->buf_size;
-		for (i = 0; i < src_cnt; i++) {
-			void *buf = thread->srcs[i];
+		for (i = 0; i < src->cnt; i++) {
+			void *buf = src->aligned[i];
 			struct page *pg = virt_to_page(buf);
 			unsigned long pg_off = offset_in_page(buf);
 
 			um->addr[i] = dma_map_page(dev->dev, pg, pg_off,
 						   um->len, DMA_TO_DEVICE);
-			srcs[i] = um->addr[i] + src_off;
+			srcs[i] = um->addr[i] + src->off;
 			ret = dma_mapping_error(dev->dev, um->addr[i]);
 			if (ret) {
 				dmaengine_unmap_put(um);
 				result("src mapping error", total_tests,
-				       src_off, dst_off, len, ret);
+				       src->off, dst->off, len, ret);
 				failed_tests++;
 				continue;
 			}
 			um->to_cnt++;
 		}
 		/* map with DMA_BIDIRECTIONAL to force writeback/invalidate */
-		dsts = &um->addr[src_cnt];
-		for (i = 0; i < dst_cnt; i++) {
-			void *buf = thread->dsts[i];
+		dsts = &um->addr[src->cnt];
+		for (i = 0; i < dst->cnt; i++) {
+			void *buf = dst->aligned[i];
 			struct page *pg = virt_to_page(buf);
 			unsigned long pg_off = offset_in_page(buf);
 
@@ -732,7 +739,7 @@ static int dmatest_func(void *data)
 			if (ret) {
 				dmaengine_unmap_put(um);
 				result("dst mapping error", total_tests,
-				       src_off, dst_off, len, ret);
+				       src->off, dst->off, len, ret);
 				failed_tests++;
 				continue;
 			}
@@ -741,30 +748,30 @@ static int dmatest_func(void *data)
 
 		if (thread->type == DMA_MEMCPY)
 			tx = dev->device_prep_dma_memcpy(chan,
-							 dsts[0] + dst_off,
+							 dsts[0] + dst->off,
 							 srcs[0], len, flags);
 		else if (thread->type == DMA_MEMSET)
 			tx = dev->device_prep_dma_memset(chan,
-						dsts[0] + dst_off,
-						*(thread->srcs[0] + src_off),
+						dsts[0] + dst->off,
+						*(src->aligned[0] + src->off),
 						len, flags);
 		else if (thread->type == DMA_XOR)
 			tx = dev->device_prep_dma_xor(chan,
-						      dsts[0] + dst_off,
-						      srcs, src_cnt,
+						      dsts[0] + dst->off,
+						      srcs, src->cnt,
 						      len, flags);
 		else if (thread->type == DMA_PQ) {
-			for (i = 0; i < dst_cnt; i++)
-				dma_pq[i] = dsts[i] + dst_off;
+			for (i = 0; i < dst->cnt; i++)
+				dma_pq[i] = dsts[i] + dst->off;
 			tx = dev->device_prep_dma_pq(chan, dma_pq, srcs,
-						     src_cnt, pq_coefs,
+						     src->cnt, pq_coefs,
 						     len, flags);
 		}
 
 		if (!tx) {
 			dmaengine_unmap_put(um);
-			result("prep error", total_tests, src_off,
-			       dst_off, len, ret);
+			result("prep error", total_tests, src->off,
+			       dst->off, len, ret);
 			msleep(100);
 			failed_tests++;
 			continue;
@@ -777,8 +784,8 @@ static int dmatest_func(void *data)
 
 		if (dma_submit_error(cookie)) {
 			dmaengine_unmap_put(um);
-			result("submit error", total_tests, src_off,
-			       dst_off, len, ret);
+			result("submit error", total_tests, src->off,
+			       dst->off, len, ret);
 			msleep(100);
 			failed_tests++;
 			continue;
@@ -793,58 +800,58 @@ static int dmatest_func(void *data)
 		dmaengine_unmap_put(um);
 
 		if (!done->done) {
-			result("test timed out", total_tests, src_off, dst_off,
+			result("test timed out", total_tests, src->off, dst->off,
 			       len, 0);
 			failed_tests++;
 			continue;
 		} else if (status != DMA_COMPLETE) {
 			result(status == DMA_ERROR ?
 			       "completion error status" :
-			       "completion busy status", total_tests, src_off,
-			       dst_off, len, ret);
+			       "completion busy status", total_tests, src->off,
+			       dst->off, len, ret);
 			failed_tests++;
 			continue;
 		}
 
 		if (params->noverify) {
-			verbose_result("test passed", total_tests, src_off,
-				       dst_off, len, 0);
+			verbose_result("test passed", total_tests, src->off,
+				       dst->off, len, 0);
 			continue;
 		}
 
 		start = ktime_get();
 		pr_debug("%s: verifying source buffer...\n", current->comm);
-		error_count = dmatest_verify(thread->srcs, 0, src_off,
+		error_count = dmatest_verify(src->aligned, 0, src->off,
 				0, PATTERN_SRC, true, is_memset);
-		error_count += dmatest_verify(thread->srcs, src_off,
-				src_off + len, src_off,
+		error_count += dmatest_verify(src->aligned, src->off,
+				src->off + len, src->off,
 				PATTERN_SRC | PATTERN_COPY, true, is_memset);
-		error_count += dmatest_verify(thread->srcs, src_off + len,
-				params->buf_size, src_off + len,
+		error_count += dmatest_verify(src->aligned, src->off + len,
+				params->buf_size, src->off + len,
 				PATTERN_SRC, true, is_memset);
 
 		pr_debug("%s: verifying dest buffer...\n", current->comm);
-		error_count += dmatest_verify(thread->dsts, 0, dst_off,
+		error_count += dmatest_verify(dst->aligned, 0, dst->off,
 				0, PATTERN_DST, false, is_memset);
 
-		error_count += dmatest_verify(thread->dsts, dst_off,
-				dst_off + len, src_off,
+		error_count += dmatest_verify(dst->aligned, dst->off,
+				dst->off + len, src->off,
 				PATTERN_SRC | PATTERN_COPY, false, is_memset);
 
-		error_count += dmatest_verify(thread->dsts, dst_off + len,
-				params->buf_size, dst_off + len,
+		error_count += dmatest_verify(dst->aligned, dst->off + len,
+				params->buf_size, dst->off + len,
 				PATTERN_DST, false, is_memset);
 
 		diff = ktime_sub(ktime_get(), start);
 		comparetime = ktime_add(comparetime, diff);
 
 		if (error_count) {
-			result("data error", total_tests, src_off, dst_off,
+			result("data error", total_tests, src->off, dst->off,
 			       len, error_count);
 			failed_tests++;
 		} else {
-			verbose_result("test passed", total_tests, src_off,
-				       dst_off, len, 0);
+			verbose_result("test passed", total_tests, src->off,
+				       dst->off, len, 0);
 		}
 	}
 	ktime = ktime_sub(ktime_get(), ktime);
@@ -857,18 +864,18 @@ static int dmatest_func(void *data)
 err_srcs_array:
 	kfree(srcs);
 err_dstbuf:
-	for (i = 0; thread->udsts[i]; i++)
-		kfree(thread->udsts[i]);
-	kfree(thread->udsts);
+	for (i = 0; dst->raw[i]; i++)
+		kfree(dst->raw[i]);
+	kfree(dst->raw);
 err_udsts:
-	kfree(thread->dsts);
+	kfree(dst->aligned);
 err_dsts:
 err_srcbuf:
-	for (i = 0; thread->usrcs[i]; i++)
-		kfree(thread->usrcs[i]);
-	kfree(thread->usrcs);
+	for (i = 0; src->raw[i]; i++)
+		kfree(src->raw[i]);
+	kfree(src->raw);
 err_usrcs:
-	kfree(thread->srcs);
+	kfree(src->aligned);
 err_free_coefs:
 	kfree(pq_coefs);
 err_thread_type:

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox