UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Observer bnewlin
Observer
1,222 Views
Registered: ‎03-10-2015

Using DMAC with dma-proxy

There is a nice writeup explaining how to use the Xilinx AXI DMA cores to do Linux DMA from userspace.  http://www.wiki.xilinx.com/Linux+DMA+From+User+Space

 

I'm attempting to take this example and adapt it to use the DMAC controller in a Zynq 7020.  The DMAC uses the mainline PL330 DMA driver under the hood when used with the DMA Engine framework. 

 

I've enabled the INTERNAL_TEST in dma_proxy.c to test a transfer in kernel space.  I've gotten the memory allocated successfully and can get to the point where a transfer attempt is made before I get a kernel OOPS.  I've tracked it down to an incorrect FIFO access.  It appears that...well there isn't one.  It must come defined in the AXI DMA core but is not present for the DMAC, so operation fails during the call to:

dma_device->device_prep_slave_sg(pchannel_p->channel_p, &pchannel_p->sglist, 1, 
						pchannel_p->direction, flags, NULL);

Does anyone know how to get a FIFO defined for the DMAC?  I've attached a snippet of my device tree and the printout when running the dma-proxy kernel module.  You can see that the fifo addr and burst_sz are both 0, which is the reason for the kernel OOPS.

 

Device tree addition for the dma-proxy driver to use the DMAC.

dma_proxy@0 {
     	compatible ="xlnx,dma_proxy";
     	dmas = <&dmac_s 0
		&dmac_s 1
		&dmac_s 2
             	&dmac_s 3>;
     	dma-names = "DMA0", "DMA1", "DMA2", "DMA3";
	memory-region = <&dma_reserved>;
  	};

Output when loading the dma-proxy module with extra printks.

 modprobe dma-proxy
dma_proxy: loading out-of-tree module taints kernel.
dma_proxy module initialized
dma_proxy_driver dma_proxy@0: assigned reserved memory node buffer@20000000
Allocating uncached memory at virtual address 0xd0380000, physical address 0x20000000
Allocating uncached memory at virtual address 0xd8380000, physical address 0x28000000
Allocating uncached memory at virtual address 0xe0380000, physical address 0x30000000
Allocating uncached memory at virtual address 0xe8380000, physical address 0x38000000
Starting internal test
DMA0 tx...
Entering transfer...
Entering start_transfer...
sg_init_table...
sg_dma_address...
0x20000000
sg_dma_len...
3145728
sg_dma_offset: 0
sg_dma_page_link: 0x2
device_prep_slave_sg...
Entering pl330_prep_slave_fifo...
pl330_dma_slave_map_dir...
pl330_unprep_slave_fifo...
Entering pl330_unprep_slave_fifo...
Exiting pl330_unprep_slave_fifo...
dma_map_resource...
fifo addr = 0x0
burst_sz = 0
dma dir = 1
Internal error: Oops - BUG: 0 [#1] PREEMPT SMP ARM
Modules linked in: dma_proxy(O+) wl18xx wlcore mac80211 cfg80211 wlcore_sdio
CPU: 0 PID: 1557 Comm: modprobe Tainted: G           O    4.14.0-xilinx-v2018.1 #14
Hardware name: Xilinx Zynq Platform
task: cee2e040 task.stack: cecaa000
PC is at pl330_prep_slave_fifo+0xc0/0x190
LR is at 0xc0a50d3c
pc : [<c0364ec8>]    lr : [<c0a50d3c>]    psr: 200c0013
sp : cecabd00  ip : 20000000  fp : c0177ad0
r10: 00000001  r9 : 00000001  r8 : 00000000
r7 : c07013fc  r6 : 00000001  r5 : ced2e000  r4 : cef23800
r3 : c0a50d3c  r2 : 0000000c  r1 : 00000000  r0 : 00000001
Flags: nzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
Control: 18c5387d  Table: 07bd404a  DAC: 00000051
Process modprobe (pid: 1557, stack limit = 0xcecaa210)
Stack: (0xcecabd00 to 0xcecac000)
bd00: cef23800 00000002 00000001 bf1092c4 c0366cec 00000000 cef23800 bf109338
bd20: 00000002 c0366d38 bf1092c4 c0366cec bf10931c 00000000 c785ec10 00000000
bd40: 0000000e bf107120 00000003 00000000 00000000 c0152b0c bf1085bf cecabd6c
bd60: bf1092c0 00300000 00000000 bf1092c0 bf109090 bf1076f0 bf107574 ced61410
bd80: bf109090 00000000 bf109090 c03d2538 ced61410 c0a5ce7c c0a5ce80 c03d107c
bda0: ced61410 ced61444 bf109090 c0a1ae08 00000000 00000001 c7d0df64 c03d11bc
bdc0: 00000000 bf109090 c03d1140 c03cf8cc cec80f58 ced63eb4 bf109090 c78cca80
bde0: 00000000 c03d06f4 bf108647 bf108648 00000000 bf109090 cecabf40 c7cb84c0
be00: bf10c000 c03d1940 ffffe000 cecabf40 c7cb84c0 c0101a74 00000000 00000001
be20: c081529e c0804722 c01c5e3c c094d2d0 c081529e c0804722 c017b094 c094d2d0
be40: c081529e c0804722 00000016 c094d2d0 cec00000 014000c0 a00d0013 c7d0df40
be60: bf109100 cecabf40 c7cb84c0 00000001 c7d0df40 c7d0df64 c0177ad0 c017bbc4
be80: bf109100 c0804722 bf109100 cecabf40 bf109148 c017b09c bf10910c 00007fff
bea0: bf109100 c0177c18 d032e000 c0177b40 c0a0ee0c bf10d000 d032e000 bf1092ac
bec0: ffffffff 000b9a68 014002c0 00000004 000b9a50 c01c55c0 c7cb84c0 00000000
bee0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
bf00: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 000032a8
bf20: 000bd140 00000000 d03312a8 000b9a68 ffffe000 00000051 000b9a50 c017b2d0
bf40: d032ec72 d032e000 000032a8 d0330d80 d0330c30 d03302d4 00003000 000031c0
bf60: 00000000 00000000 00000000 00001b2c 0000001e 0000001f 00000019 00000016
bf80: 00000012 00000000 000032a8 000b9e91 000b9858 00000080 c01071c4 cecaa000
bfa0: 00000000 c0107000 000032a8 000b9e91 000b9e98 000032a8 000b9a68 000b9e91
bfc0: 000032a8 000b9e91 000b9858 00000080 000b98f8 000b88f0 00000001 000b9a50
bfe0: bebd0ab8 bebd0aa8 00020ebc b6e9fe50 600d0010 000b9e98 5c5fff7d 57f7fdf0
[<c0364ec8>] (pl330_prep_slave_fifo) from [<c0366d38>] (pl330_prep_slave_sg+0x4c/0x1ac)
[<c0366d38>] (pl330_prep_slave_sg) from [<bf107120>] (transfer+0xe8/0x2a8 [dma_proxy])
[<bf107120>] (transfer [dma_proxy]) from [<bf1076f0>] (dma_proxy_probe+0x17c/0x298 [dma_proxy])
[<bf1076f0>] (dma_proxy_probe [dma_proxy]) from [<c03d2538>] (platform_drv_probe+0x50/0x9c)
[<c03d2538>] (platform_drv_probe) from [<c03d107c>] (driver_probe_device+0x1ec/0x2b0)
[<c03d107c>] (driver_probe_device) from [<c03d11bc>] (__driver_attach+0x7c/0xa8)
[<c03d11bc>] (__driver_attach) from [<c03cf8cc>] (bus_for_each_dev+0x7c/0x8c)
[<c03cf8cc>] (bus_for_each_dev) from [<c03d06f4>] (bus_add_driver+0x16c/0x1d4)
[<c03d06f4>] (bus_add_driver) from [<c03d1940>] (driver_register+0xa0/0xe0)
[<c03d1940>] (driver_register) from [<c0101a74>] (do_one_initcall+0xfc/0x11c)
[<c0101a74>] (do_one_initcall) from [<c017bbc4>] (do_init_module+0x54/0x1c4)
[<c017bbc4>] (do_init_module) from [<c017b09c>] (load_module+0x1d8c/0x1e90)
[<c017b09c>] (load_module) from [<c017b2d0>] (SyS_init_module+0x130/0x144)
[<c017b2d0>] (SyS_init_module) from [<c0107000>] (ret_fast_syscall+0x0/0x48)
Code: e3570000 01a07003 e3560002 9a000000 (e7f001f2)
---[ end trace 581574cac86f6521 ]---
0 Kudos
2 Replies
Observer bnewlin
Observer
1,158 Views
Registered: ‎03-10-2015

Re: Using DMAC with dma-proxy

A little more research into DMAC section of the Zynq-7000 TRM (ug585) describes it as containing a "128 (64-bit) word MFIFO to buffer the data that the controller writes or reads during a transfer".  It does not seem to be externally addressable, either manually or by device tree definition, so the dma-proxy driver can't access it using the DMA Engine that I can tell.

 

However, I'm realizing that I may not need to use the device_prep_slave_sg() function at all because I'm doing a memory to memory DMA transfer.  I'm transferring data from the FPGA memory in the PL to a reserved memory section in system memory.  This section is mapped to userspace.  For this type of transfer, I think I need to use device_prep_dma_memcpy(), which does not internally call the pl330_prep_slave_fifo() function, which requires a fifo address be defined (and which is causing my kernel OOPS).

 

If I were doing a DEV_TO_MEM or MEM_TO_DEV transfer, I think I would need to add an AXI Streaming FIFO, or something of the sort, in order to get an addressable FIFO for the device_prep_slave_sg() function to use.

 

In the dma-proxy driver, I'm replacing

chan_desc = dma_device->device_prep_slave_sg(pchannel_p->channel_p, &pchannel_p->sglist, 1, 
					     pchannel_p->direction, flags, NULL);

with

chan_desc = dma_device->device_prep_dma_memcpy(pchannel_p->channel_p, pchannel_p->dma_handle, 
		                              SRC_ADDRESS, 4, flags);

This test copies one register from the FPGA to the reserved memory.  Initial results are promising.  I'll keep updating this as I go until I either have a working kernel module, or I crash and burn.  Someone may find it helpful.  At the very least, I will.

 

 

0 Kudos
Highlighted
Observer cj01
Observer
767 Views
Registered: ‎11-11-2018

Re: Using DMAC with dma-proxy

Hi bnewlin, did you ever solvethis problem? I came across the same issue while running the dma proxy module on Zybo board Linux system.

Tags (2)
0 Kudos