GithubHelp home page GithubHelp logo

bperez77 / xilinx_axidma Goto Github PK

View Code? Open in Web Editor NEW
449.0 41.0 225.0 277 KB

A zero-copy Linux driver and a userspace interface library for Xilinx's AXI DMA and VDMA IP blocks. These serve as bridges for communication between the processing system and FPGA programmable logic fabric, through one of the DMA ports on the Zynq processing system. Distributed under the MIT License.

License: MIT License

Makefile 11.83% C 88.17%
xilinx zedboard dma-driver xilinx-axi-dma xilinx-axi-vdma userspace-dma fpga fpga-dma axi-dma axi-vdma

xilinx_axidma's Introduction

Xilinx AXI DMA Driver and Library (Quick Start Guide)

Build Status

Overview

A zero-copy, high-bandwidth Linux driver and userspace interface library for Xilinx's AXI DMA and VDMA IP blocks. The purpose of this software stack is to allow userspace Linux applications to interact with hardware on the FPGA fabric. The driver and userspace library act as a generic layer between the procesor and FPGA, and abstracts away the details of setting up DMA transactions. The pupose of AXI DMA and VDMA IP blocks is to serve as bridges for communication between the processing system and the FPGA, through one of the DMA ports on the Zynq processing system.

The driver enables userspace application to allocate zero-copy, physically contiguous DMA buffers for transfers, allowing for high bandwidth communication between the FPGA and ARM core. The driver exposes its functionality via a character device, which the library interacts with.

This driver supports 4.x version Xilinx kernels. It has been tested with the mainline Xilinx kernel, and the Analog Devices' kernel on the Zedboard. The driver should work with any 4.x kernel and any board that uses a Zynq-7000 series processing system.

Fork with Multi-Process Support

At the moment, the driver only supports a single process accessing the AXI DMA/VDMA IP engines. There is a fork of the repository that has support for multiple processes accessing independent DMA engines by @corna. You can find that fork here. Independent DMA engines can be opened by a single process; however, each engine still can only be used by one process at a time. Thus, two processes can not share the TX and RX channels of an engine.

In the future, the driver will have proper synchronization for both multiple processes and multiple threads. In the meantime, if you need multi-process support, the fork is a good workaround.

Features

  1. Zero-copy transmit (processor to FPGA), receive (FPGA to processor), and two-way combined DMA transfers.
  2. Support for transfers with Xilinx's AXI DMA and AXI VDMA (video DMA) IP blocks.
  3. Allocation of DMA buffers that are contiguous in physical memory, allowing for high-bandwidth DMA transfers, through the kernel's contiguous memory allocator (CMA).
  4. Allocation of memory that is coherent between the FPGA and processor, by disabling caching for those pages in the DMA buffer.
  5. Synchronous and asynchronous modes for transfers.
  6. Registration of callback functions that are called when an asynchronous transfer completes.
  7. Delivery of a POSIX real-time signal upon completion of an asynchronous transfer.
  8. Support for DMA buffer sharing, or external DMA buffers. Currently the driver can only import a DMA buffer from another driver. This is useful, for example, when transfers need to be done with a frame buffer allocated by a DRM driver.

Setting Up the Driver

Linux Kernel

The driver depends on the contiguous memory allocator (CMA), Xilinx's DMA and VDMA driver, and DMA buffer sharing. These must be enabled in the kernel the driver is complied against. These should be enabled by default in any Xilinx Linux kenrel fork. To be sure, make sure to double check the kernel configuration by running make menuconfig or by opening the .config file at the top level of your kernel source tree. The following options should be enabled:

CONFIG_CMA=y
CONFIG_DMA_CMA=y
CONFIG_XILINX_DMAENGINES=y
CONFIG_XILINX_AXIDMA=y
CONFIG_XILINX_AXIVDMA=y
CONFIG_DMA_SHARED_BUFFER=y

Device Tree

The driver requires a node in the device tree. This node describes the DMA channels that the driver has exclusive access. It is also used to probe the driver, so the driver is activited only when this node is present. The node has the following properties:

  • compatible - This must be the string "xlnx,axidma-chrdev". This is used to match the driver with the device tree node.
  • dmas - A list of phandles (references to other device tree nodes) of Xilinx AXI DMA or VDMA device tree nodes, followed by either 0 or 1. This refers to the child node inside of the Xilinx AXI DMA/VDMA device tree node, 0 of course being the first child node.
  • dma-names - A list of names for the DMA channels. The names can be completely arbitrary, but they must be unique. This is required by the DMA interface function dma_request_slave_channel(), but is otherwise unused by the driver. In the future, the driver will use the names in printed messages.

For the Xilinx AXI DMA/VDMA device tree nodes, the only requirement is that the device-id property is unique, but they can be completely arbitrary. This is how the channels are referred to in both the driver and from userspace. For more information on creating AXI DMA/VDMA device tree nodes, consult the kernel documentation for them.

Here is a simple example of the device tree nodes for a system with a single AXI DMA IP, with both a transmit and receive channel. Note you will need to adjust this for your kernel tree and setup:

axidma_chrdev: axidma_chrdev@0 {
    compatible = "xlnx,axidma-chrdev";
    dmas = <&axi_dma_0 0 &axi_dma_0 1>;
    dma-names = "tx_channel", "rx_channel";
};

axi_dma_0: axidma0@40400000 {
    #dma-cells = <1>;
    compatible = "xlnx,axi-dma", "xlnx,axi-dma-6.03.a", "xlnx,axi-dma-1.00.a";
    reg = <0x40400000 0x10000>;
    clocks = <&clkc 15>, <&clkc 15>, <&clkc 15>, <&clkc 15>;
    clock-names = "s_axi_lite_aclk", "m_axi_sg_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk";    
    xlnx,include-sg;    
    xlnx,addrwidth = <32>;

    dma-mm2s-channel@40400000 {
        compatible = "xlnx,axi-dma-mm2s-channel";
        dma-channels = <1>;
        xlnx,datawidth = <64>;
        xlnx,device-id = <0>;
        interrupt-parent = <&intc>;
        interrupts = <0 29 4>;
    };
    
    dma-s2mm-channel@40400000 {
        compatible = "xlnx,axi-dma-s2mm-channel";
        dma-channels = <1>;
        xlnx,datawidth = <64>;
        xlnx,device-id = <1>;
        interrupt-parent = <&intc>;
        interrupts = <0 30 4>;
    };
};

Kernel Command Line

The contiguous memory allocator works by reserving a pool of memory for contiguous memory allocations that it uses when requested. By default this size is too small for typical uses with this driver. The size can be changed by appending cma=<size>M to the kernel command line arguments. This sets the pool's size to size MBs.

The kernel command line can be updated by changing the device tree or from the U-Boot console. For example, to set the CMA's pool size to 25 MB from the U-Boot console:

setenv bootargs "${bootargs} cma=25M"

NOTE: In the future, specifying the CMA region size will be moved into the device tree, so this will not be necessary.

Compilation

Makefile Variables

The Makefile supports both native and cross compilation, and is repsonsible for compiling the driver and a few example programs. It has the following variables:

  • CROSS_COMPILE - The prefix for the compiler to use for cross-compilation.
  • ARCH - The architecture being compiled for. Required for compiling the driver when cross-compiling.
  • KBUILD_DIR - The path to the kernel source tree to compile the driver against. The kernel must already be built. Required for compiling the driver.
  • OUTPUT_DIR - The path to the output directory to place the generated files in. Defaults to outputs in the top-level directory.
  • XILINX_DMA_INCLUDE_PATH_FIXUP - This specifies to fixup the issue with the location of the xilinx_dma.h header file in the kernel being compiled against. Specify this if you see an include error when compiling the driver.

For a complete list of targets, and a more complete description of the options, run:

make help

The Makefile also supports specifying these variables in a configuration file. The repository distirbutes a template for this file at config_template.mk. To use this file, copy it to config.mk, and uncomment and fill in the varaibles as needed.

Compiling the Driver

The Makefile supports out-of-tree compilation for the driver. To compile the driver, you must specify the path to a kernel source tree that is already built. Also, you can specify any cross-compilation options as necessary. For example, to compile the driver for ARM:

make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm KBUILD_DIR=</path/to/kernel/tree> driver

This will generate a kernel object for the driver at outputs/axidma.ko.

Compiling the Examples

The driver and library come with several example programs that show how to use the API. There's a program that benchmarks a two-way transfer, one that transmits a file over a channel, and one that displays an image (assuming the proper hardware is there). Consult the command line help for each program on usage. To cross-compile the examples for ARM:

make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm examples

This will generate executables for the examples under outputs.

Compiling and Using the Library

The userspace library is compiled the typical shared object file. To compile the library for ARM:

make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm library

This will generate a shared object file for the AXI DMA library at outputs/libaxidma.so.

To use the library with your application, you need to compile your program against the library, by specifying the flags -I </path/to/repo>/include -L </path/to/repo>/outputs/ -l axidma when compiling. Then, so the executable can find the library at runtime, you need to copy the library file to the board's filesytem. You can either copy to one of the default system library directories, such as /usr/lib/, or you can add the outputs directory to the LD_LIBRARY_PATH environment variable. See how the examples programs are compiled in their Makefile.

Generating the Library Documentation

The userspace library has Doxygen documentation for its interface. To generate and view this documentation, run:

make library_docs

This will generate both HTML and Latex documentation for the AXI DMA library under docs. This will also open up the HTML documentation in Firefox.

Running an Application

Before you run an application that uses the AXI DMA software stack, you must make sure that the driver has been inserted into the kernel. This can be accomplished with:

insmod axidma.ko

This should create a character device for the driver at /dev/axidma. To verify that the insertion was successful, run dmesg to view the kernel log messages. You should see a message like the following:

axidma: axidma_dma.c: 672: DMA: Found 1 transmit channels and 1 receive channels.
axidma: axidma_dma.c: 674: VDMA: Found 0 transmit channels and 0 receive channels.

Naturally, the numbers will vary based on your specific configuration.

Debugging Issues with the Software Stack

The driver prints out a detailed message every time that it encounters an error to the kernel log message buffer. If the library says that an error occured, run dmesg to see the kernel log. The driver will print out a detailed message, along with the file, function, and line number that the error occured on.

There is an issue with the location of the Xilinx DMA header file, xilinx_dma.h in the Xilinx kernels. In between the 3.x and 4.x version, the location of this file changed, but certain 4.x kernels still use the old location from the 3.x kernel. If you see an error message like the following when compiling the driver, then specify the XILINX_DMA_INCLUDE_PATH_FIXUP Makefile variable when compiling:

In file included from /home/bmperez/projects/xilinx_axidma/driver/axidma_dma.c:24:0:
/home/bmperez/projects/xilinx_axidma/driver/version_portability.h:25:68: fatal error: linux/dma/xilinx_dma.h: No such file or directory
 #include <linux/dma/xilinx_dma.h>   // Xilinx DMA config structures
                                                                    ^
compilation terminated.

Using the Driver with a PetaLinux Kernel

For how to add the driver to a PetaLinux project and build it against a PetaLinux kernel, see issue #24.

Limitations/To-Do's

  1. There is currently no explicit support for concurrency, so only one thread should access the driver at a time.
  2. The character device is opened in exclusive mode, so only one process can access the driver at a time.
  3. The driver cannot export DMA buffers for sharing, it only supports importing at the moment.
  4. There is no support for multi-channel mode.

Additional Information

For more detailed information, including how to boot Linux on the Zedboard, and how to run a simple DMA loopback example to test the software stack's functionality, see the wiki.

References

Xilinx's AXI VDMA and DMA Driver - Source Code

Xilinx's AXI DMA Test Driver (Shows How to Write a Driver to Use Xilinx's AXI DMA Driver) - Source Code

Documentation on Xilinx AXI DMA Device Tree Node Bindings - Documentation

Documentation for DMA Device Tree Bindings - Documentation

Documentation for CMA (reserved memory regions) Device Tree Bindings - Documentation

Documentation on DMA Buffer Sharing - Documentation

Documentation for Xilinx's AXI DMA IP Core (Vivado 2015.2, Version 7.1) - Documentation

Documentation for Xilinx's AXI VDMA IP Core (Vivado 2015.2, Version 6.2) - Documentation

License (MIT)

The MIT License (MIT)

Copyright (c) 2015-2016 Brandon Perez [email protected]
Copyright (c) 2015-2016 Jared Choi

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

xilinx_axidma's People

Contributors

baum55 avatar bperez77 avatar iainmarcuson avatar sploet avatar woodmeister123 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

xilinx_axidma's Issues

Move Contiguous Memory Region Specification to the Device Tree

To allocate large regions of physically-contiguous memory, the driver uses the CMA (contiguous memory allocator). At boot time, the user specifies the cma=<size>M parameter to reserve a region of size megabytes for the CMA.

It would be much nicer if the user could instead specify this in the device tree, as this requires less manual user intervention, since they don't need to update the command line via U-Boot or the device tree.

This can be done via a reserved memory region device tree node. The user specifies a device tree node that describes the contiguous memory region (size, alignment, type, etc.). Then the user would put the memory-region property in the driver's device tree node. This is simply a phandle to the reserved memory region device tree node. See the reserved-memory documentation for more details.

Problem with callback function

Hi Brandon,

I tried to register a callback function for the RX channel using the axidma_set_callback() function. I modified the benchmark example for that reason, but unfortunately, the callback function is never triggered.

After some debugging I came a bit closer to the root of the problem. In the library function axidma_callback() the signal from the kernel driver is evaluated and the previously registered callback function (if any) is triggered. For some reason, the channel ID derived from the signal is always 0, while my callback function is registered for channel 1 (RX), so it will never be triggered.

I registered a second callback function for the TX channel for testing. When starting the modified benchmark example with "-n 10" parameter, the axidma_callback() function is called 10 times, but it should be 20, since we have 10 TX and 10 RX operations. It seems that no signal is emitted for the RX operation.

Edit: I should mention that I tried these things with VDMA and c3181d8 version.

rx channel works well but tx channel always timed out?

Hello, I only use the rx channel before and this driver works well. When I need to do bi-directional operation, it fails.

My block design is quite typical AXI-DMA usage, the S2MM (write channel) receives data from peripheral device, write to DDR, and then the MM2S (read channel) reads the data from DDR and send to another xilinx IP.

To implement this, I call the axidma_oneway_transfer() twice, the first call to rx data, and the second call to tx data. I have verified the buffer after rx done to make sure it works well, but the tx never finish, and report "DMA transmit transaction timed out".

I remember that I have tried the axidma_twoway_transfer() with a loop design before, and it works, so I am wondering why the tx fails with two axidma_oneway_transfer() calls?

axidma: axidma_dma.h: axidma_request_channels: 621: Unable to get slave channel 0: tx_channel.

Hi Brandon,
I'm trying to use your driver on a zedboard, petalinux system.When i run insmod axidma.ko command to load driver,the error in the title comes up.

This is the error log:
root@dmaTest:/lib/modules/4.6.0-xilinx/extra# insmod axidma.ko
axidma: axidma_dma.h: axidma_request_channels: 621: Unable to get slave channel 0: tx_channel.
axidma: probe of axidma_chrdev@0 failed with error -38

And my device tree of dma part is:

 axidma_chrdev: axidma_chrdev@0 {
		compatible = "xlnx,axidma-chrdev";
		dmas = <&axi_dma_0 0 &axi_dma_0 1>;
		dma-names = "tx_channel", "rx_channel";
};
amba_pl: amba_pl {
	#address-cells = <1>;
	#size-cells = <1>;
	compatible = "simple-bus";
	ranges ;
	
	
	axi_dma_0: dma@40400000 {
		#dma-cells = <1>;
		clock-names = "s_axi_lite_aclk", "m_axi_sg_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk";
		clocks = <&clkc 15>, <&clkc 15>, <&clkc 15>, <&clkc 15>;
		compatible = "xlnx,axi-dma-1.00.a";
		interrupt-parent = <&intc>;
		interrupts = <0 29 4 0 30 4>;
		reg = <0x40400000 0x10000>;
		xlnx,include-sg ;
		dma-mm2s-channel@40400000 {
			compatible = "xlnx,axi-dma-mm2s-channel";
			dma-channels = <0x1>;
			interrupts = <0 29 4>;
			xlnx,datawidth = <0x20>;
			xlnx,device-id = <0x0>;
		};
		dma-s2mm-channel@40400000 {
			compatible = "xlnx,axi-dma-s2mm-channel";
			dma-channels = <0x1>;
			interrupts = <0 30 4>;
			xlnx,datawidth = <0x20>;
			xlnx,device-id = <0x1>;
		};
	};
};

I didn't change anything for you driver,but where there is a problem.
Thanks for any help you can offer.

Copy Targets to the Output Directory

Currently, the Makefile builds the targets directly in the specified outputs directory (through the OUTPUT command line specification). It is cleaner and prevents unnecessary rebuilding if the targets are built in their local directories, then copied to the outputs directory. The Makefile will be updated to accomdate this.

AXI DMA not found

Hello,
I'm trying to install xilinx_axidma driver. For drive coppile I using petalinux with 4.9.0-xilinx-v2017.4 kernel version. After system build I get only messages like these:

dma-pl330 f8003000.dmac: Loaded driver for PL330 DMAC-241330
dma-pl330 f8003000.dmac: DBUFF-128x8bytes Num_Chans-8 Num_Peri-4 Num_Events-16
xilinx-vdma 40400000.dma: Xilinx AXI DMA Engine Driver Probed!!
xilinx_axidma: loading out-of-tree module taints kernel.

#lsmod
Tainted: G
xilinx_axidma 19976 0 - Live 0x7f031000 (O)

In /proc/devices I not see axi_dma

My device-tree:

	axi_dma_0: dma@40400000 {
		#dma-cells = <0x1>;
		clock-names = "s_axi_lite_aclk", "m_axi_sg_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk";
		clocks = <0x1 0xf 0x1 0xf 0x1 0xf 0x1 0xf>;
		compatible = "xlnx,axi-dma", "xlnx,axi-dma-6.03.a", "xlnx,axi-dma-1.00.a";
		interrupt-parent = <0x4>;
		interrupts = <0x0 0x1d 0x4 0x0 0x1e 0x4>;
		reg = <0x40400000 0x10000>;
		xlnx,addrwidth = <0x40>;
		xlnx,include-sg;

		dma-channel@40400000 {
			compatible = "xlnx,axi-dma-mm2s-channel";
			dma-channels = <0x1>;
			interrupts = <0x0 0x1d 0x4>;
			xlnx,datawidth = <0x20>;
			xlnx,device-id = <0x0>;
		};

		dma-channel@40400030 {
			compatible = "xlnx,axi-dma-s2mm-channel";
			dma-channels = <0x1>;
			interrupts = <0x0 0x1e 0x4>;
			xlnx,datawidth = <0x20>;
			xlnx,device-id = <0x1>;
		};
	};
};

axidma_chrdev: axidma_chrdev@0 {
    compatible = "xlnx,axidma-chrdev";
    dmas = <&axi_dma_0 0 &axi_dma_0 1>;
    dma-names = "tx_channel", "rx_channel";
};`

Support of SG mode

Do I understand correctly that this the character driver and the library does not support scatter gather mode?

xlnx-3.19 dependancies

I am using Petalinux 2015.2 (xlnx-3.19 kernel). I found these issues and did a quick hack as I do not use VDMA:

struct xilinx_vdma_config has no member vsize, hsize, stride
I commented out all assignments to xilinx_vdma_config
XILINX_DMA_IP_VDMA undeclared
I commented out conditional and assigned XILINX_DMA_IP_DMA
DMA_COMPL_SKIP_DEST_UNMAP undeclared
( 1 << 3 ) in another kernel

This resulted in a successful (untested) build

VDMA: axidma_prep_transfer only configures first frame buffer address

When using the driver with a VDMA core with more than one framebuffer (e.g., with xlnx,num-fstores = <0x2>), the frame buffer addresses beyond the first are not configured.

This is the lines which seem to configure the first frame buffer address (from axidma_prep_transfer in axidma_dma.c):

        dma_template.dst_start = sg_dma_address(&sg_list[0]);
        dma_template.src_start = sg_dma_address(&sg_list[0]);

There is no reference to the other entries of the sg_list.

The VDMA core starts running nonetheless, but frame buffer addresses beyond the first are set to 0x00000000. I don't know what the implications of this are.

Also I don't know the Xilinx VDMA driver well enough... would it work to replace the call to dmaengine_prep_interleaved_dma with a call to dmaengine_prep_slave_sg, like in the non-VDMA case?

Use the Channel Name in Log Messages

The user provides names for the channels in the device tree configuration, so the driver can use it when printing out error messages to identify which specific channel failed.

xilinx-dma 40400000.dma: Channel ded141d0 has errors 11 cdr 0 cdr msb 0 tdr 0 tdr msb 0

Hi Brandon,
I send data from PS to the PL side by "axidma_oneway_transfer()", then the PS side process do nothing but waitting for an interrupt generate by gpio ip core in PL side, which indicate the data just send from the PS side have done with some process and is ready to send back to the PS. Once the PS side capture the interrupt signal, it will use "axidma_oneway_transfer()" to read the data from PL, but the data length after PL process is not equal the length send from PS.
A error message printed each time the PS done one packet loopback(send to PL and read back),which is "xilinx-dma 40400000.dma: Channel ded141d0 has errors 11 cdr 0 cdr msb 0 tdr 0 tdr msb 0".
Yesterday i change the program in PL side to make the data length equal to the length send from PS,but the error still appear.
Do you have any idea why this error appear? If this error can be safely ignored,how could i make the zed do not print the error message?
Thanks very much fo your great project.

app test

Hello, I tested your axidma_benchmark application, the test is successful, you can provide me an application?I want to write an array of their own definition tx_buf, my hardware circuit is to short the two channels, This function is sent through axidma_twoway_transfer go read in rx_buf array I sent, the program written for a period of time can not be adjusted, beg you give a template program.

axidma_chrdev.c: axidma_mmap: 276: Unable to allocate contiguous DMA memory region of size 41472000.

Hi Brandon,
I'm trying to use your driver on a zedboard but the error in the title comes up, I tried increasing to cma=45M in the hope that it would fix the issue but it doesn't.

After booting, in the dmesg I can see the following lines relevant to the issue:
[ 0.000000] cma: Reserved 48 MiB at 0x1b800000
[ 0.000000] Memory policy: Data cache writealloc
[ 0.000000] On node 0 totalpages: 131072
[ 0.000000] free_area_init_node: node 0, pgdat c0938ec0, node_mem_map dfbe0000
[ 0.000000] Normal zone: 1024 pages used for memmap
[ 0.000000] Normal zone: 0 pages reserved
[ 0.000000] Normal zone: 131072 pages, LIFO batch:31
[ 0.000000] percpu: Embedded 12 pages/cpu @dfbbd000 s19776 r8192 d21184 u49152
[ 0.000000] pcpu-alloc: s19776 r8192 d21184 u49152 alloc=12*4096
[ 0.000000] pcpu-alloc: [0] 0 [0] 1
[ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 130048
[ 0.000000] Kernel command line: console=ttyPS0,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 cma=45M rootwait
[ 0.000000] PID hash table entries: 2048 (order: 1, 8192 bytes)
[ 0.000000] Dentry cache hash table entries: 65536 (order: 6, 262144 bytes)
[ 0.000000] Inode-cache hash table entries: 32768 (order: 5, 131072 bytes)
[ 0.000000] Memory: 461696K/524288K available (5286K kernel code, 231K rwdata, 1848K rodata, 1024K init, 222K bss, 13440K reserved, 49152K cma-reserved, 0K highmem)
[ 0.000000] Virtual kernel memory layout:
vector : 0xffff0000 - 0xffff1000 ( 4 kB)
fixmap : 0xffc00000 - 0xfff00000 (3072 kB)
vmalloc : 0xe0800000 - 0xff800000 ( 496 MB)
lowmem : 0xc0000000 - 0xe0000000 ( 512 MB)
pkmap : 0xbfe00000 - 0xc0000000 ( 2 MB)
modules : 0xbf000000 - 0xbfe00000 ( 14 MB)
.text : 0xc0008000 - 0xc07f78d8 (8127 kB)
.init : 0xc0800000 - 0xc0900000 (1024 kB)
.data : 0xc0900000 - 0xc0939c20 ( 232 kB)
.bss : 0xc0939c20 - 0xc0971624 ( 223 kB)

U-boot reads the uEnv.txt file from the BOOT partition and uses those bootargs instead of the ones in the device tree, here's my uEnv.txt file:

uenvcmd=run adi_sdboot
adi_sdboot=echo Copying Linux from SD to RAM... && fatload mmc 0 ${kernel_load_address} ${kernel_image} && fatload mmc 0 ${devicetree_load_address} ${devicetree_image} && if fatload mmc 0 ${ramdisk_load_address} ${ramdisk_image}; then bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}; else bootm ${kernel_load_address} - ${devicetree_load_address}; fi
bootargs=console=ttyPS0,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 cma=45M rootwait

This is working properly as shown by the dmesg log.

I'm using u-boot and linux cloned from the xilinx repositories, I checked out the tag xilinx-v2016.3 and made a branch with those before compiling them.
I'm using the rootfs I got from linaro-vivid-developer-20151215-714.tar.gz from the linaro website.
Linux version 4.6.0-xilinx (root@osboxes) (gcc version 5.2.1 20151005 (Linaro GCC 5.2-2015.11-2) )

My device tree is the one generated by hsi 2016.3 which I then edited to give a unique names to the channels and add the node for your driver.
Here is the relevant .dtsi file

/ {

	axidma_chrdev: axidma_chrdev@0 {
	    compatible = "xlnx,axidma-chrdev";
	    dmas = <&axi_dma_0 0 &axi_dma_0 1>;
	    dma-names = "tx_channel", "rx_channel";
	};

	amba_pl: amba_pl {
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "simple-bus";
		ranges ;
		axi_dma_0: dma@40400000 {
			#dma-cells = <1>;
			clock-names = "s_axi_lite_aclk", "m_axi_sg_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk";
			clocks = <&clkc 15>, <&clkc 15>, <&clkc 15>, <&clkc 15>;
			compatible = "xlnx,axi-dma-1.00.a";
			interrupt-parent = <&intc>;
			interrupts = <0 29 4 0 30 4>;
			reg = <0x40400000 0x10000>;
			xlnx,addrwidth = <0x20>; //NB 20h = 32b
			dma-channel@40400000 {
				compatible = "xlnx,axi-dma-mm2s-channel";
				dma-channels = <0x1>;
				interrupts = <0 29 4>;
				xlnx,datawidth = <0x20>; 
				xlnx,device-id = <0x0>;
			};
			dma-channel@40400030 {
				compatible = "xlnx,axi-dma-s2mm-channel";
				dma-channels = <0x1>;
				interrupts = <0 30 4>;
				xlnx,datawidth = <0x20>; 
				xlnx,device-id = <0x1>;
			};
		};
	};
};

Thanks for any help you can offer.

Unknown symbol xilinx_vdma_channel_set_config

Hello, I'm work with Linux kernel version of:

# uname-r
4.6.0-xilinx-22223-gcda28de-dirty

I'm allocate CMA of 64M and this is my dmesg output.
This is my part of device tree.
And when I try load axidma.ko, I get:

# insmod axidma.ko 
insmod: can't insert 'axidma.ko': Invalid argument
# dmesg | tail
xilinx-vdma 80400000.dma: Xilinx AXI VDMA Engine Driver Probed!!
axidma: no symbol version for xilinx_vdma_channel_set_config
axidma: Unknown symbol xilinx_vdma_channel_set_config (err -22)

But by on Linux kernel of 3.17 this module is loading.
Firstly, I thought that this because Xilinx DMA driver doesn't load with Linux kernel and System.map doesn't have line about xilinx_vdma_channel_set_config. But if upload Xilinx DMA driver manually, the kallsyms will be have this line.
If work with kernel of 3.17, when start benchmark, I get:

# ./axidma_benchmark 
AXI DMA Benchmark Parameters:
	Transmit Buffer Size: 7.91 Mb
	Receive Buffer Size: 7.91 Mb
	Number of DMA Transfers: 1000 transfers

Using transmit channel 0 and receive channel 1.
Segmentation fault

and if transfer (file kek.txt has some text):

# ./axidma_transfer kek.txt lel.txt 
AXI DMA File Transfer Info:
	Transmit Channel: 0
	Receive Channel: 1
	Input File Size: 0.00 Mb
	Output File Size: 0.00 Mb

Segmentation fault

Output of dmesg after this execution

Offset of a user space virtual address is ignored

I call the function "axidma_oneway_transfer()" from the lib in my application and I wanted to add an offset to the buffer.
I have 2 threads. 1 thread who reads the data from the FPGA and another thread who process the data.
To make sure that the processed data are not overridden, I wanted to add an offset to the allocated buffer.
First I read to buf, then to buf + offset, then to buf + 2*offset and so on.

For example:
char* buf = (char*)axidma_malloc(axidma_dev, 100);
axidma_oneway_transfer(axidma_dev, rx_chans->data[0], buf + 10, 10, true);

But the data are always written to the base address of buf and not buf + offset (in the example: buf + 10).
Is this the desired behavior?

Driver doesn`t work on AARCH64

I have cma=256M and using ultrascale+ (xilinx ZCU102 devboard with ARM64 chip)

Have a look at my log:

[ 0.000000] Linux version 4.9.0-dirty (roman@ws-278) (gcc version 6.2.1 20161114 (Linaro GCC Snapshot 6.2-2016.11) ) #76 SMP Sat Oct 21 12:01:12 +03 2017
[ 0.000000] Boot CPU: AArch64 Processor [410fd034]
[ 0.000000] earlycon: cdns0 at MMIO 0x00000000ff000000 (options '115200n8')
[ 0.000000] bootconsole [cdns0] enabled
[ 0.000000] cma: Reserved 256 MiB at 0x000000006d800000
[ 0.000000] psci: probing for conduit method from DT.
[ 0.000000] psci: PSCIv1.0 detected in firmware.
[ 0.000000] psci: Using standard PSCI v0.2 function IDs
[ 0.000000] psci: MIGRATE_INFO_TYPE not supported.
[ 0.000000] percpu: Embedded 19 pages/cpu @ffffffc87ff6f000 s40088 r8192 d29544 u77824
[ 0.000000] Detected VIPT I-cache on CPU0
[ 0.000000] CPU features: enabling workaround for ARM erratum 845719
[ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 1034240
[ 0.000000] Kernel command line: earlycon clk_ignore_unused
[ 0.000000] log_buf_len individual max cpu contribution: 131072 bytes
[ 0.000000] log_buf_len total cpu_extra contributions: 393216 bytes
[ 0.000000] log_buf_len min size: 131072 bytes
[ 0.000000] log_buf_len: 524288 bytes
[ 0.000000] early log buf free: 129092(98%)
[ 0.000000] PID hash table entries: 4096 (order: 3, 32768 bytes)
[ 0.000000] Dentry cache hash table entries: 524288 (order: 10, 4194304 bytes)
[ 0.000000] Inode-cache hash table entries: 262144 (order: 9, 2097152 bytes)
[ 0.000000] software IO TLB [mem 0x69800000-0x6d800000] (64MB) mapped at [ffffffc069800000-ffffffc06d7fffff]
[ 0.000000] Memory: 3786472K/4194304K available (5822K kernel code, 412K rwdata, 1796K rodata, 320K init, 382K bss, 145688K reserved, 262144K cma-reserved)
[ 0.000000] Virtual kernel memory layout:
[ 0.000000] modules : 0xffffff8000000000 - 0xffffff8008000000 ( 128 MB)
[ 0.000000] vmalloc : 0xffffff8008000000 - 0xffffffbebfff0000 ( 250 GB)
[ 0.000000] .text : 0xffffff8008080000 - 0xffffff8008630000 ( 5824 KB)
[ 0.000000] .rodata : 0xffffff8008630000 - 0xffffff8008800000 ( 1856 KB)
[ 0.000000] .init : 0xffffff8008800000 - 0xffffff8008850000 ( 320 KB)
[ 0.000000] .data : 0xffffff8008850000 - 0xffffff80088b7008 ( 413 KB)
[ 0.000000] .bss : 0xffffff80088b7008 - 0xffffff8008916814 ( 383 KB)
[ 0.000000] fixed : 0xffffffbefe7fd000 - 0xffffffbefec00000 ( 4108 KB)
[ 0.000000] PCI I/O : 0xffffffbefee00000 - 0xffffffbeffe00000 ( 16 MB)
[ 0.000000] vmemmap : 0xffffffbf00000000 - 0xffffffc000000000 ( 4 GB maximum)
[ 0.000000] 0xffffffbf00000000 - 0xffffffbf1dc00000 ( 476 MB actual)
[ 0.000000] memory : 0xffffffc000000000 - 0xffffffc880000000 ( 34816 MB)

After linux kernel loaded, i successfully insert kernel module:

# insmod /axidma.ko

[ 163.886158] axidma: loading out-of-tree module taints kernel.
[ 163.892920] axidma: axidma_dma.c: axidma_dma_init: 706: DMA: Found 1 transmit channels and 1 receive channels.
[ 163.902946] axidma: axidma_dma.c: axidma_dma_init: 708: VDMA: Found 0 transmit channels and 0 receive channels.

Next i tried to do the benchmark test:

# /axidma_benchmark

AXI DMA Benchmark Parameters:
Transmit Buffer Size: 7.91 Mb
Re[ 287.820644] axidma: axidma_chrdev.c: axidma_mmap: 277: Unable to allocate contiguous DMA memory region of size 8294400.
ceive Buffer Size: 7.91 Mb
Number of DMA Transfers: 10 transfe[ 287.837036] axidma: axidma_chrdev.c: axidma_mmap: 278: Please make sure that you specified cma= on the kernel command line, and the size is large enoug.
rs

axidma_benchmark: tx_size=8294400
libaxidma: mmap size=8294400
Unable to allocate transmit buffer from the AXI DMA device.: Cannot allocate memory

# dmesg

163.886158] axidma: loading out-of-tree module taints kernel.
[ 163.892645] cma: cma_alloc(cma ffffff80088eac40, count 8, align 3)
[ 163.892767] cma: cma_alloc(): returned ffffffbf017f4e00
[ 163.892798] cma: cma_alloc(cma ffffff80088eac40, count 1, align 0)
[ 163.892820] cma: cma_alloc(): returned ffffffbf017f4fc0
[ 163.892849] cma: cma_alloc(cma ffffff80088eac40, count 8, align 3)
[ 163.892872] cma: cma_alloc(): returned ffffffbf017f5180
[ 163.892891] cma: cma_alloc(cma ffffff80088eac40, count 1, align 0)
[ 163.892913] cma: cma_alloc(): returned ffffffbf017f4ff8
[ 163.892920] axidma: axidma_dma.c: axidma_dma_init: 706: DMA: Found 1 transmit channels and 1 receive channels.
[ 163.902946] axidma: axidma_dma.c: axidma_dma_init: 708: VDMA: Found 0 transmit channels and 0 receive channels.
[ 287.820644] axidma: axidma_chrdev.c: axidma_mmap: 277: Unable to allocate contiguous DMA memory region of size 8294400.
[ 287.837036] axidma: axidma_chrdev.c: axidma_mmap: 278: Please make sure that you specified cma= on the kernel command line, and the size is large enough.

I foud out that function dma_alloc_coherent always return NULL.
The same behaviour is for all buffer size i have set (16 byte, 1024 byte, 8Kb, 16 Kb, 128Kb, 1Mb, 16 Mb, etc..).

Yesterday I also found the same trouble in the Internet, and seem it was solved : ikwzm/udmabuf@b4ee3e3#diff-80d2ae607f6046e637a24ce2bc06ba30

I am not a kernel guru, can you help we with with?
Do you have any idea?

Add Multi-Channel DMA Support

The Zynq processing system has a limited number of DMA channels, so sharing the channel between multiple agents can be useful, if they have low bandwidth requirements.

Possible member omission in axidma_request_channels()

In axidma_request_channels() line 645, the if statement compares variable chan to NULL. From looking at some of the kernel code, it looks a check on chan->chan should be done, since chan is dereferenced in the previous line.

DMA Completion Status

I've come to learn that there are one of two ways an interrupt will be triggered when DMAing data from the PL to the PS...

Case 1. Data stream hits a TLAST signal and generates an interrupt based on EOF (End of Frame)

Case 2. Number of bytes requested to be transferred is reached and generates an interrupt based on IOC (Interrupt on Complete)

Optimally TLAST would always be concurrent with the last byte of the transfer that was requested so an interrupt would show both EOF and IOC if I am understanding correctly

There are some xilinx forum discussions on the subject such as this one for reference
https://forums.xilinx.com/t5/Embedded-Processor-System-Design/Axi-DMA-S2MM-Is-it-necessary-to-assert-TLAST/td-p/743336

What I would like to do is validate why we got an interrupt and ensure that a transaction got all the data that was requested. Maybe your driver does this already in some fashion, but how would I go about checking the status of a DMA transaction complete interrupt?

axidma_benchmark example fails with sizes of 16384 bytes or larger

@bperez77 First let me say thanks for your hard work on bridging the gap Xilinx left for us.

I'm experiencing an issue using your axidma_benchmark example in my system. I've played around with this quite a bit now and found that I can successfully run the example as long as the transmit and receive size remains under 16384 bytes, however once I attempt a transfer of 16384 bytes like so...
./axidma_benchmark -b 16384 -s 16384 the test fails resulting in the message "Failed to perform the AXI DMA read-write transfer: Timer expired"

Interestingly, once it's failed like this it doesn't seem to matter what size I use, it will fail. This seems to indicate that something in the DMA process is in a stuck state.

Also interesting, if I just run the full 8MB test after a fresh linux boot, it doesn't result in a timeout, but rather most of the receive buffer is just unchanged as indicated by your message...
"Warning: 99.95% of the receive buffer matches the initialization pattern.
This may mean that the receive buffer was not properly updated.
Single transfer test successfully completed!"

Here is some info on my setup...
Hardware: ZedBoard
Vivado Version: 2017.4
PetaLinux Version: 2017.3
Image of my block diagram attached
dma_loopback

I use the PetaLinux system-user.dtsi file to add the necessary items to the device tree like this...
/include/ "system-conf.dtsi"
/ {
axidma_chrdev: axidma_chrdev@0 {
compatible = "xlnx,axidma-chrdev";
dmas = <&axi_dma_0 0 &axi_dma_0 1>;
dma-names = "tx_channel", "rx_channel";
};

amba_pl: amba_pl {
	#address-cells = <1>;
	#size-cells = <1>;
	compatible = "simple-bus";
	ranges ;
	axi_dma_0: dma@40400000 {
		#dma-cells = <1>;
		clock-names = "s_axi_lite_aclk", "m_axi_sg_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk";
		clocks = <&clkc 15>, <&clkc 15>, <&clkc 15>, <&clkc 15>;
		compatible = "xlnx,axi-dma-1.00.a";
		interrupt-parent = <&intc>;
		interrupts = <0 29 4 0 30 4>;
		reg = <0x40400000 0x10000>;
		xlnx,addrwidth = <0x20>;
		dma-channel@40400000 {
			compatible = "xlnx,axi-dma-mm2s-channel";
			dma-channels = <0x1>;
			interrupts = <0 29 4>;
			xlnx,datawidth = <0x20>;
			xlnx,device-id = <0x0>;
		};
		dma-channel@40400030 {
			compatible = "xlnx,axi-dma-s2mm-channel";
			dma-channels = <0x1>;
			interrupts = <0 30 4>;
			xlnx,datawidth = <0x20>;
			xlnx,device-id = <0x1>;
		};
	};
};

};

Side questions that may provide some clue...

  1. Does your driver care if the hardware DMA is setup for Scatter-Gather or not? I assumed it would work with or without this feature turned on.
  2. Does your driver care about the datawidth of the DMA? As you can see in my case it's currently 32, but it could have been 64 or even as much as 1024 in AXI DMA v7.1

Any help on this issue would be greatly appreciated!

can vdma loop work ?

use dma ip ,the driver,examples worked well, but vdma cant:

Z-turn# ./axidma_benchmark -v
AXI DMA Benchmark Parameters:
Transmit Buffer Size: 7.91 Mb
Receive Buffer Size: 7.91 Mb
Number of DMA Transfers: 1000 transfers

Using transmit channel 0 and receive channel 1.
axidma: axidma_dma.c: axidma_start_transfer: 298: VDMA receive transaction timed out.
Failed to perform the AXI DMA read-write transfer: Timer expired

how can i use vdma driver?

single dma data loss

Hi,
I'm trying to transfer data stream with ZUC102. PS receives data from PL fifo using DMA, then transfers it through wifi. Incoming data rate is lower than 30MBps,DMA clock runs at 300MBps.

20180404183713

In order to periodically inform wifi thread that data id ready, I had to use single DMA. PL burst length is 256 bytes, fifo length is 32 KBytes.

I noticed that between each 2 transfers, there was always a data loss, even if I did nothing else but DMA transfer, no matter what size DMA buffer is. Console printed that "channel has errors 10"

Debugging showed that PL fifo was never full. What could possibly have caused data loss? Thanks

Not finding tx_channel in device tree

Brandon,
I seem to be having a problem finding the channels in the device tree. Below is the device tree node which is really just a copy of yours with a couple of changes. Can you suggest anything?

Brandon,
I'm quite a bit closer but now running into "axidma: axidma_dma.c: axidma_request_channels: 649: Unable to get slave channel 0: tx_channel." Here's my device tree node:

axidma_chrdev: axidma_chrdev@0 {
compatible = "xlnx,axidma-chrdev";
dmas = <&axi_dma_0 0 &axi_dma_0 1>;
dma-names = "tx_channel", "rx_channel";
};

axi_dma_0: axidma0@a0000000 {
#dma-cells = <1>;
compatible = "xlnx,axi-dma", "xlnx,axi-dma-6.03.a", "xlnx,axi-dma-1.00.a";
reg = <0x0 0xa0000000 0x0 0x10000>;
clocks = <0x42>, <0x42>, <0x42>, <0x42>;
clock-names = "s_axi_lite_aclk", "m_axi_sg_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk";
xlnx,include-sg;
xlnx,addrwidth = <0x20>;

dma-mm2s-channel@a0000000 {
    compatible = "xlnx,axi-dma-mm2s-channel";
    dma-channels = <1>;
    xlnx,datawidth = <64>;
    xlnx,device-id = <0>;
    interrupt-parent = <0x4>;
    interrupts = <0 29 4>;
};

dma-s2mm-channel@a0000030 {
    compatible = "xlnx,axi-dma-s2mm-channel";
    dma-channels = <1>;
    xlnx,datawidth = <64>;
    xlnx,device-id = <1>;
    interrupt-parent = <0x4>;
    interrupts = <0 30 4>;
};

};

cant find driver at /dev/axidma after insmod

hey brandon, i didnt add your cma args into my bootargs, then i run the insmod and look up the dmesg, it shows that
[ 113.487763] random: nonblocking pool is initialized, i think if it was the bootargs problem ?

this is my boot args
console=ttyPS0,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 rootwait devtmpfs.mount=0

Add a config.mk File to Allow for User Configurations

It can quickly become tedious to always have to specify the cross-compiler and location of the kernel source tree for compilation on the command-line. It would be nicer instead if the user could specify these files in a Makefile configuration file, and then not have to think about them each time they invoke make.

Fix Issue With Location of xilinx_dma.h

The purpose file version_portability.h is to deal with the differences between Linux 3.x and 4.x. This is to deal with changes to the generic DMA interface, and changes to Xilinx's AXI DMA driver. One of these changes is the location of xilinx_dma.h.

In 3.x versions, it was located under include/linux/amba/xilinx_dma.h and in 4.x it was typically located under include/linux/dma/xilinx_dma.h. However, not all 4.x versions of the Xilinx kernel obey this. For example, the Analog Device's fork of the kernel has the file under include/linux/amba/xilinx_dma.h. This was originally spawned by discussion in issue #1. The branch xilinx-v2015.4 of the mainline Xilinx kernel has this problem as well.

Thus, to deal with this quirk, the file has to updated to allow for a new macro that specifies to use the alternate location for the 4.x version. This should be able to be specified from the Makefile command line.

DMA receive transaction timed out

I have a block design with AXI_DMA IP included, and I have verify it with bare metal system. Then I follow the README to build the driver/device tree/app. The "axidma.ko" can be inserted successfully, but the example apps all fail with " DMA receive transaction timed out ", Does anybody run into this problem before?

Here is my device tree:

/ {
amba_pl: amba_pl {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges ;
axidma_chrdev: axidma_chrdev@0 {
compatible = "xlnx,axidma-chrdev";
dmas = <&axi_dma_0 0 &axi_dma_0 1>;
dma-names = "tx_channel", "rx_channel";
};
axidmatest_0: axidmatest@0{
compatible = "xlnx,axi-dma-test-1.00.a";
dmas = <&axi_dma_0 0 &axi_dma_0 1>;
dma-names = "axidma0", "axidma1";
};
axi_dma_0: dma@40400000 {
#dma-cells = <1>;
compatible = "xlnx,axi-dma-1.00.a";
interrupt-parent = <&intc>;
interrupts = <0 29 4 0 30 4>;
reg = <0x40400000 0x10000>;
dma-mm2s-channel@40400000 {
compatible = "xlnx,axi-dma-mm2s-channel";
dma-channels = <1>;
interrupts = <0 29 4>;
xlnx,datawidth = <0x20>;
xlnx,device-id = <0x0>;
};
dma-s2mm-channel@40400030 {
compatible = "xlnx,axi-dma-s2mm-channel";
dma-channels = <1>;
interrupts = <0 30 4>;
xlnx,datawidth = <0x20>;
xlnx,device-id = <0x1>;
};
};
axi_gpio_0: gpio@41200000 {
#gpio-cells = <2>;
compatible = "xlnx,xps-gpio-1.00.a";
gpio-controller ;
reg = <0x41200000 0x10000>;
xlnx,all-inputs = <0x0>;
xlnx,all-inputs-2 = <0x0>;
xlnx,all-outputs = <0x0>;
xlnx,all-outputs-2 = <0x0>;
xlnx,dout-default = <0x00000000>;
xlnx,dout-default-2 = <0x00000000>;
xlnx,gpio-width = <0x1>;
xlnx,gpio2-width = <0x20>;
xlnx,interrupt-present = <0x0>;
xlnx,is-dual = <0x0>;
xlnx,tri-default = <0xFFFFFFFF>;
xlnx,tri-default-2 = <0xFFFFFFFF>;
};
};
};

and here is what I saw in Linux command line.

root@zedboard-zynq7:# cd xilinx_axidma/
root@zedboard-zynq7:
/xilinx_axidma# ls
axidma.ko axidma_display_image axidma_transfer
axidma_benchmark axidma_plps
root@zedboard-zynq7:/xilinx_axidma# insmod axidma.ko
axidma: axidma_dma.c: axidma_dma_init: 705: DMA: Found 1 transmit channels and 1 receive channels.
axidma: axidma_dma.c: axidma_dma_init: 707: VDMA: Found 0 transmit channels and 0 receive channels.
root@zedboard-zynq7:
/xilinx_axidma# ./axidma_benchmark
AXI DMA Benchmark Parameters:
Transmit Buffer Size: 7.91 Mb
Receive Buffer Size: 7.91 Mb
Number of DMA Transfers: 1000 transfers

Using transmit channel 0 and receive channel 1.
axidma: axidma_dma.c: axidma_start_transfer: 298: DMA receive transaction timed out.
xilinx-dma 40400000.dma: Cannot stop channel df5f81d0: 0
Failed to perform the AXI DMA read-write transfer: Timer expired

Transactions failures when a DDR PL is instanciated

Hi,

Fisrt of all, many thanks for sharing your driver. I have got it working pretty good with your loop-back example and with my particular Vivado design. In this last, I have a flow of data which comes in a FIFO and which is read back from this last thanks to a DMA.

Furthermore, because of my application case need a large amoung of memory, I use a external DDR memory that I control in the PL thanks to the MIG IP (like in a basic design design which is provided by Xilinx for their Mini-itx evaluation board for example - http://microzed.org/design/2056/17).

But, when this DDR PL is instanciated in my PetaLinux project, I get the following error from the driver: "xilinx-vdma 40400000.dma: Channel df035910 has errors 40, cdr 0 tdr 0" and the transaction doesn't occur.

I used a trick to 'overcome' this issue but it isn't satisfy as I disable the MIG device directly in the device tree:
&PLDDR3_IP_MIG_PL_DDR3 {
reg = <0x80000000 0x00000000>;
};
Linux doesn't see any more this external DDR so the transaction doesn't occur into it, but this external memory becomes useless...

Have you any suggestion?

DMA receive transaction timed out

Hi bperez77,

I am trying to install your driver for using with DMA on petalinux 2017.4 and run into some problems.
Here is what I have done:

root@zynq_petalinux:/lib/modules/4.9.0-xilinx-v2017.4/extra# insmod ./xilinx-axidma.ko 
xilinx_axidma: loading out-of-tree module taints kernel.
axidma: axidma_dma.c: axidma_dma_init: 706: DMA: Found 1 transmit channels and 1 receive channels.
axidma: axidma_dma.c: axidma_dma_init: 708: VDMA: Found 0 transmit channels and 0 receive channels.

It is OK.

root@zynq_petalinux:/usr/bin# ./axidma_benchmark -i 1 -o 1
AXI DMA Benchmark Parameters:
        Transmit Buffer Size: 1.00 Mb
        Receive Buffer Size: 1.00 Mb
        Number of DMA Transfers: 1000 transfers

Using transmit channel 0 and receive channel 1.
axidma: axidma_dma.c: axidma_start_transfer: 298: DMA receive transaction timed out.`

What's the problem?Thank you.

Running multiple DMA IPs

Can your driver be attached to and run multiple DMA IPs (concurrently or one at a time)? If not do you have any plans to extend the driver to support multiple DMAs?

Any idea about xilinx-dma 40400000.vdma: Channel ded141d0 has errors 40 cdr 0 tdr 0

Hi Brandon,

In the first, thanks for your driver. I spent a lot time on Xilinx dma.
I got many help from it rather than Xilinx support....
The driver can work on Loopback environment, but I encounter some DMA decode error when I poring this driver on my own IP.
My IP using only one rx channel to receive data from ADC peripheral.
The interrupt will cause this error occurred and I didn't get any data.

Do you have any idea to help me to solve this error?

My device tree as below:
` chosen {
bootargs = "console=ttyPS0,115200 earlyprintk uio_pdrv_genirq.of_id=generic-uio cma=25M ";
};

amba_pl: amba_pl {
    axi_dma_0: dma@40400000 {
        #dma-cells = <1>;                                                                                                                                                                                                                                                                                                 
        clock-names = "s_axi_lite_aclk", "m_axi_sg_aclk", "m_axi_s2mm_aclk";
        clocks = <&clkc 15>, <&clkc 15>, <&clkc 15>;
        compatible = "xlnx,axi-dma-1.00.a";
        interrupt-parent = <&intc>;
        interrupts = <0 29 4>;
        reg = <0x40400000 0x10000>;
        xlnx,addrwidth = <0x20>;
        dma-channel@40400030 {
            compatible = "xlnx,axi-dma-s2mm-channel";
            dma-channels = <0x1>;
            interrupts = <0 29 4>;
            xlnx,datawidth = <0x40>;
            xlnx,device-id = <0x0>;
        };
    };
axidma_chrdev: axidma_chrdev@0 {
    compatible = "xlnx,axidma-chrdev";
    dmas = <&axi_dma_0 0>;
    dma-names =  "rx_channel";
};  

};
`

Thanks
Stanley

AXI DMA IP changes in Vivado 2018.1

Xilinx officially released Vivado 2018.1 today and they have made some changes which may effect your driver as can be seen here...

https://www.xilinx.com/support/documentation/ip_documentation/axi_dma/v7_1/pg021_axi_dma.pdf

The main item of note is that the IP core now supports up to 64MB transfers!

It looks to me like the Xilinx Driver has not yet been updated (at least on github) to handle this increase in max transfer size as line 165 shows...
#define XILINX_DMA_MAX_TRANS_LEN_MAX 23
...and it should be 26

https://github.com/Xilinx/linux-xlnx/blob/master/drivers/dma/xilinx/xilinx_dma.c

only one (tx) vdma channel recognized

Hello,

please, help to solve the problem...

I have a Zynq board (7020) running Linux (Linaro 4.4).

My design is using Xilinx VDMA IP Core configured in a loopback mode.

If I try insmod axidma.ko driver (and dmesg | grep dma) then only one VDMA channel (tx) is recognized. The driver reads the info about channels from the device-tree but it does not see the rx channel. Instead it finds the not configured (and non-existing) DMA receive channel...

Here are my VDMA and driver nodes in devicetree.dts:

axi_vdma_0: axivdma@40030000 {
compatible = "xlnx,axi-vdma", "xlnx,axi-vdma-6.2", "xlnx,axi-vdma-1.00.a";
#dma-cells = <1>;
reg = < 0x40030000 0x10000 >;
dma-ranges = <0x00000000 0x00000000 0x40000000>;
xlnx,num-fstores = <0x8>;
xlnx,flush-fsync = <0x1>;
xlnx,addrwidth = <0x20>;
clocks = <&clkc 15>, <&clkc 15>, <&clkc 15>, <&clkc 15>, <&clkc 15>;
clock-names = "s_axi_lite_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk",
"m_axis_mm2s_aclk", "s_axis_s2mm_aclk";
dma-channel@40030000 {
compatible = "xlnx,axi-vdma-mm2s-channel";
interrupts = < 0 54 4 >;
xlnx,datawidth = <0x40>;
} ;
dma-channel@40030030 {
compatible = "xlnx,axi-vdma-s2mm-channel";
interrupts = < 0 53 4 >;
xlnx,datawidth = <0x40>;
} ;
} ;

axidma_chrdev: axidma_chrdev@0 {
compatible = "xlnx,axidma-chrdev";
dmas = <&axi_vdma_0 0 &axi_vdma_0 1>;
dma-names = "tx_channel", "rx_channel";

};

The messages from the axidma driver after insmod:

axidma: axidma_dma.c: axidma_dma_init: 674: DMA: Found 0 transmit channels and 1 receive channels.
axidma: axidma_dma.c: axidma_dma_init: 676: VDMA: Found 1 transmit channels and 0 receive channels.

I have no entry for AXI DMA in the device tree nor there is no AXI DMA in the design. Only AXI VDMA is present in the design and devicetree...

The Linux (Xilinx) VDMA driver says:

xilinx-vdma 43000000.axivdma: Xilinx AXI VDMA Engine Driver Probed!!

Am I missing something or there is a problem with the driver itself, please?

Thank you for your help!

Erorr in axidma_setup_vdma_config(struct xilinx_vdma_config *dma_config) function

Have a look at the file axidma_dma.c for the function "static void axidma_setup_vdma_config (*******):

// Setup the config structure for VDMA

static void axidma_setup_vdma_config(struct xilinx_vdma_config *dma_config)
{
memset(dma_config, 0, sizeof(dma_config));

dma_config->frm_dly = 0;            // Number of frames to delay
dma_config->gen_lock = 0;           // Genlock, VDMA runs on fsyncs
dma_config->master = 0;             // VDMA is the genlock master
dma_config->frm_cnt_en = 1;         // Interrupt based on frame count
dma_config->park = 0;               // Continuously process all frames
dma_config->park_frm = 0;           // Frame to stop (park) at (N/A)
dma_config->coalesc = 1;            // Interrupt after one frame completion
dma_config->delay = 0;              // Disable the delay counter interrupt
dma_config->reset = 0;              // Don't reset the channel
dma_config->ext_fsync = 0;          // VDMA handles synchronizes itself
return;

}

I think that string

**memset(dma_config, 0, sizeof(dma_config));**

is needed for the cleaning a "struct dma_config", so you have to provide the size of the struct, something like this:

**memset(dma_config, 0, sizeof(struct xilinx_vdma_config));**

BTW, My Respect for software your created. It is really cool.
I am trying to run it on the zynq ultrascale+ and have some issues.
Look at here please: #27

axidma_oneway_transfer: 2 tlast signals?

Hello @bperez77 first of all thank you for sharing your code.
I have a problem that makes me tired :) Basically, I have a system where i do not know the amount of data that I have to receive back from the PL so i have a setup like that

DMA mm2s -> FIFO -> SYSTEM -> FIFO -> ASK_DATA -> FIFO -> DMA s2mm
Now I'm doing the test by removing the system block
DMA mm2s -> -> FIFO -> ASK_DATA -> FIFO -> DMA s2mm
However, when I send the data and try to collect back with small chunk the second time that i call ASK_DATA from the PS the DMA is blocked. I made some debugging with the debug ip core and I see that even if I'm sending only one time N packets on the first fifo I see 2N packets. In fact the DMA is sending 2 times the tlast signal and I don't know why. please see the image:

screenshot from 2017-11-02 18-59-38

For making the transmit I'm using the one way transfer

rc = axidma_oneway_transfer(dev, tx_channel, tx_buf, NUM_PACKETS * sizeof(u32), true);

have you ever inexperienced an issue like that? I'm making something wrong? Is there a specific limitation on the DMA parameters that I can use? I'm using petalinux and Vivado 2016.4

Thanks,

Simon

Using the driver with Petalinux

I tried compiling the driver using the Makefile you provided, however it seems to me that the KBUILD_DIR parameter is not correct.

"make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm KBUILD_DIR=..../petalinux-test/zynq-3/build/tmp/work-shared/plnx_arm/kernel-source/ driver"

This gives me the following error:

"make: *** No rule to make target '/home/lklemmer/Documents/Studium/Bachelorarbeit/petalinux-test/zynq-3/kernel-source/Module.symvers', needed by 'driver/axidma.ko'. Stop."

I noticed that petalinux put the Module.symvers file in a seprate directory (kernel-build-artifacts/)
I tried copying the contents of this directory into the linux kernel-sources (kernel-sources/) but without success.

[axidma_init_sg_entry: 98] Requested transfer address does not fall.

we ran axidma_twoway_transfer function several times,
however I failed to run in 5th step with the error axidma: axidma_dma.c: axidma_init_sg_entry: 98: Requested transfer address (null) does not fall within a previously allocated DMA buffer.
Did you guys have some problem like this so far ?? our When we get the error axidma: axidma_dma.c: axidma_init_sg_entry: 98: ??

the part of code executing axidma_twoway_transfer is,

  printf("Start twoway transfer\n");
  rc = axidma_twoway_transfer(axidma_dev, tx_channel, (void*)tx_buf, tx_size,
                                          rx_channel, (void*)rx_buf, rx_size, true);
  if (rc < 0) {
    goto stop_rem;
  }
  printf("Finished twoway transfer\n");

  stop_rem:
    stop_remainder_transactions(axidma_dev, tx_channel, rx_channel, tx_size);
    printf("Error: single transfer\n");

I pasted actual error message I got below.
I wanted to repeat this loop 8 times but, after 4th loop, suddenly raise the error and every after executions failed....

root@zynq:~# ./multi_kernel_load_module.elf
Start twoway transfer
Finished twoway transfer
Start twoway transfer
Finished twoway transfer
Start twoway transfer
Finished twoway transfer
Start twoway transfer
Finished twoway transfer
Start twoway transfer
axidma: axidma_dma.c: axidma_init_sg_entry: 98: Requested transfer address   (null) does not fall within a previously allocated DMA buffer.
Failed to perform the AXI DMA read-write transfer: Bad address
Eraxidma: axidma_dma.c: axidma_init_sg_entry: 98: Requested transfer address 00000003 does not fall within a previously allocated DMA buffer.
ror: single transfer
Start twoway transfer
Failed to perform theaxidma: axidma_dma.c: axidma_init_sg_entry: 98: Requested transfer address   (null) does not fall within a previously allocated DMA buffer.
 AXI DMA read-write transfer: Bad address
axidma: axidma_dma.c: axidma_init_sg_entry: 98: Requested transfer address   (null) does not fall within a previously allocated DMA buffer.

Start twoway transfer
Failed to perform the AXI DMA read-write transfer: Bad address
Error: single transfer
Start twoway transfer
Failed to perform the AXI DMA read-write transfer: Bad address
Error: single transfer
Start twoway transfer
xilinx-vdma 40400000.dma: Channel cc1d7b10 has errors 10, cdr 0 tdr 0
Finished twoway transfer

VDMA loopback does not work on MPSOC

anybody get VDMA loopback working on MPSOC(ZCU102)?
vdmatest works fine but when I tried examples/benchmark with -v option I got a segmentation fault, and kernel NULL pointer exception.

here is the console output.

25.093002] xilinx_axidma: loading out-of-tree module taints kernel.
[ 25.100086] axidma: axidma_dma.c: axidma_dma_init: 705: DMA: Found 0 transmit channels and 0 receive channels.
[ 25.110113] axidma: axidma_dma.c: axidma_dma_init: 707: VDMA: Found 1 transmit channels and 1 receive channels.

./benchamark -v;

64.747284] axidma: axidma_dma.c: axidma_start_transfer: 297: VDMA receive transaction timed out.
[ 64.756174] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[ 64.764253] pgd = ffffffc05635e000
[ 64.767605] [00000000] *pgd=0000000055f68003
[ 64.771689] , *pud=0000000055f68003
[ 64.777066] , *pmd=0000000000000000
[ 64.779006]
[ 64.782438] Internal error: Oops: 86000006 [#1] SMP
[ 64.789254] Modules linked in: xilinx_axidma(O) uio_pdrv_genirq
[ 64.797107] CPU: 0 PID: 2068 Comm: benchmark Tainted: G O 4.9.0-xilinx-v2017.2 #1
[ 64.807778] Hardware name: ZynqMP ZCU102 RevB (DT)
[ 64.814596] task: ffffffc055e48480 task.stack: ffffffc055f90000
[ 64.822542] PC is at 0x0
[ 64.827073] LR is at 0x0
[ 64.831606] pc : [<0000000000000000>] lr : [<0000000000000000>] pstate: a0000145
[ 64.841091] sp : ffffffc055f93d80
[ 64.846500] x29: 0000000000001e00 x28: ffffffc055f90000
[ 64.853903] x27: ffffff8008942000 x26: 000000000000001d
[ 64.861329] x25: 0000000000000123 x24: 0000000000000015
[ 64.868775] x23: 0000007ff2e3bd40 x22: 0000007ff2e3bd40
[ 64.876238] x21: ffffffc055f93dd0 x20: 0000007ff2e3bd40
[ 64.883662] x19: ffffffc0571ab900 x18: 0000000000000010
[ 64.891057] x17: 0000000000000000 x16: 0000000000000000
[ 64.898451] x15: 0000000000000006 x14: 69746361736e6172
[ 64.905818] x13: 7420657669656365 x12: ffffff80089b4060
[ 64.913179] x11: ffffffc05598e650 x10: 000000000000018b
[ 64.920522] x9 : 00000000ffffffff x8 : 0000000000000003
[ 64.927833] x7 : 0000000000000004 x6 : 0000000059c01000
[ 64.935101] x5 : ffffffc055c09780 x4 : ffffffc0561afc40
[ 64.942360] x3 : ffffffc0561afbe8 x2 : 0000000000000004
[ 64.949600] x1 : 0000000000000140 x0 : 00000000ffffffc2
[ 64.956815]
[ 64.960212] Process benchmark (pid: 2068, stack limit = 0xffffffc055f90020)
[ 64.969136] Stack: (0xffffffc055f93d80 to 0xffffffc055f94000)
[ 64.976820] 3d80: ffffffc055f93e00 ffffff800819dc14 ffffffc056ed7800 ffffffc05596cd58
[ 64.986592] 3da0: ffffffc056ed7800 0000007ff2e3bd40 0000007ff2e3bd40 0000000000000015
[ 64.996385] 3dc0: 0000007f9d5f8000 ffffffc055f93ec0 0000000000000001 0000007f9d5f9000
[ 65.006197] 3de0: 00000000007e9000 0000000000000001 0000007f9ce10000 00000000007e9000
[ 65.015993] 3e00: ffffffc055f93e80 ffffff800819e304 ffffffc056ed7800 0000000000000003
[ 65.025768] 3e20: ffffffc056ed7800 0000000080305706 0000007ff2e3bd40 0000000000401010
[ 65.035566] 3e40: ffffffc055f93e80 ffffff800818c68c ffffffc0558a8700 ffffffc0558a8700
[ 65.045371] 3e60: 000000002adf0010 000000000000001c ffffffc055f93e80 ffffff800819e2e4
[ 65.055175] 3e80: 0000000000000000 ffffff8008082ef0 0000000000000000 00000000007e9000
[ 65.064974] 3ea0: ffffffffffffffff 0000007f9dea014c 0000000060000000 0000000000000000
[ 65.074763] 3ec0: 0000000000000003 0000000080305706 0000007ff2e3bd40 00000000007e9000
[ 65.084552] 3ee0: 0000000000000001 0000007f9ce10000 00000000007e9000 0000000000000001
[ 65.094336] 3f00: 000000000000001d 0000000000000000 0000000000000001 000000002adf1090
[ 65.104072] 3f20: 000000002adf10b8 0000000000000002 0000000000000000 000000000000028e
[ 65.113740] 3f40: 0000000000413ab8 0000007f9dea0140 0000000000040900 00000000007e9000
[ 65.123390] 3f60: 00000000007e9000 0000000000000001 0000000000413af0 0000000000000000
[ 65.133012] 3f80: 0000007f9ce10000 00000000007e9000 0000000000000000 0000000000000002
[ 65.142584] 3fa0: 0000007f9d5f9000 0000007ff2e3bd20 000000000040211c 0000007ff2e3bd20

Modules linked in: xilinx_axidma(O) uio_pdrv_genirq

Hi Brandon,
I found a strange question. The DMA driver can work well without this statement:system("Any instruction") in C language source code.Here's what I did.
axidma_init(); axidma_malloc(); axidma_oneway_transfer(); axidma_oneway_transfer();
The result is correct.When I insert this statement:system("sync") ,like this:
axidma_init(); axidma_malloc(); axidma_oneway_transfer(); system("sync"); system("sync"); axidma_oneway_transfer();
An error has occurred.
Unable to handle kernel NULL pointer dereference at virtual address 00000005 pgd = eebb8000 [00000005] *pgd=00000000 Internal error: Oops - BUG: 805 [#1] PREEMPT SMP ARM Modules linked in: xilinx_axidma(O) uio_pdrv_genirq CPU: 0 PID: 1157 Comm: myapp Tainted: G O 4.9.0-xilinx-v2017.4 #13 Hardware name: Xilinx Zynq Platform task: ef353680 task.stack: ee898000 PC is at axidma_vma_close+0xa8/0xd4 [xilinx_axidma] LR is at axidma_vma_close+0x64/0xd4 [xilinx_axidma] pc : [<bf00c450>] lr : [<bf00c40c>] psr: 60000013 sp : ee899df0 ip : ef7da558 fp : 00000034 r10: 00000001 r9 : 00000012 r8 : 00000001 r7 : 00000000 r6 : ee815c00 r5 : c0112880 r4 : ee9aab00 r3 : ef0ccf10 r2 : 00000001 r1 : 00000000 r0 : ee9aab00 Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none Control: 18c5387d Table: 2ebb804a DAC: 00000051 Process myapp (pid: 1157, stack limit = 0xee898210)
Function system() caused the error to occur.

SG mode doesn`t work well

Hi there!

I found out that this software (Scatter Gather mode) will not work properly if transfer data size more than 2^23 (8 Mb).
Yesterday I saw the sources and found out that in SG mode only one pice of data is used.
So it`s impossible to send data more than 2^23 because of IP core limitation.

I think it is possible to divide transfer data size to pieces of 8Mb and create SG list with more than one element, am I right?

Get Rid of Hierarchical Makefiles

These are a real pain to maintain, and can quickly get messy. Instead, configuration Makefiles can be included into the main Makefile to achieve the same effect.

The build system should be converted, and these configuration files will be stored under makefiles.

Missing devicetree entry

Hello,

I'm working on an Xilinx Zynq device and would like to use your driver for the AXI DMA, in order to be able to interface from a linux application to the logic in the FPGA. I'm currently running the kernel version 4.0 maintained by xilinx under the branch xilinx-v2015.4. The compile process of your driver worked flawlessly. But when trying to insert the module into the running kernel, nothing happens. After some debugging I realised, that the driver is looking for a devicetree entry with the compatible string xlnx,axidma-chrdev. However I cannot find the devicetree entry. Am I missing something? Please help.
Thank you in advance, I'm looking forward to your answer.

Add DMA Loopback Vivado Project as an Example

The simplest example to use the AXI DMA IP is to setup a loopback, where the output of the block is hooked up to its input, creating a simple loopback system. Any data sent through the system will be transfered back to the processor.

To this end, a Vivado TCL script needs to be created that will setup the Vivado project for this, and generate the bitstream file to program the FPGA with.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.