User space mappable dma buffer device driver for Linux.
User space mappable dma buffer device driver for Linux.
u-dma-buf is a Linux device driver that allocates contiguous memory blocks in the kernel space as DMA buffers and makes them available from the user space. It is intended that these memory blocks are used as DMA buffers when a user application implements device driver in user space using UIO (User space I/O).
A DMA buffer allocated by u-dma-buf can be accessed from the user space by opening the device file (e.g. /dev/udmabuf0) and mapping to the user memory space, or using the read()/write() functions.
CPU cache for the allocated DMA buffer can be disabled by setting the O_SYNC flag
when opening the device file. It is also possible to flush or invalidate CPU cache
while retaining CPU cache enabled.
The physical address of a DMA buffer allocated by u-dma-buf can be obtained by
reading /sys/class/u-dma-buf/udmabuf0/phys_addr.
The size of a DMA buffer and the device minor number can be specified when
the device driver is loaded (e.g. when loaded via the insmod command).
Some platforms allow to specify them in the device tree.
Figure 1. Architecture
The predecessor of u-dma-buf is udmabuf. The kernel module name has been changed from "udmabuf" to "u-dma-buf". The purpose of this is to avoid duplicate names because another kernel module with the same name as "udmabuf" has been added since Linux Kernel 5.x.
| Categoly | udmabuf | u-dma-buf |
|---|---|---|
| module name | udmabuf.ko | u-dma-buf.ko |
| source file | udmabuf.c | u-dma-buf.c |
| sys class name | /sys/class/udmabuf/ | /sys/class/u-dma-buf/ |
| DT compatible prop. | "ikwzm,udmabuf-0.10.a" | "ikwzm,u-dma-buf" |
This repository contains a Makefie. Makefile has the following Parameters:
| Parameter Name | Description | Default Value |
|---|---|---|
| ARCH | Architecture Name | $(shell uname -m | sed -e s/arm.*/arm/ -e s/aarch64.*/arm64/ -e s/riscv.*/riscv/ ) |
| KERNEL_SRC | Kernel Source Directory | /lib/modules/$(shell uname -r)/build |
| CONFIG_U_DMA_BUF_DEBUG | Enable debug report | y |
| CONFIG_U_DMA_BUF_QUIRK_MMAP | Enable quirk-mmap | y |
| CONFIG_U_DMA_BUF_IN_KERNEL_FUNCTIONS | Enable in-kernel functions | y |
| CONFIG_U_DMA_BUF_IOCTL | Enable ioctl | y |
| CONFIG_U_DMA_BUF_EXPORT | Enable PRIME DMA-BUFS export | y |
If you have a cross-compilation environment for target system, you can compile with:
shell$ make ARCH=arm KERNEL_SRC=/home/fpga/src/linux-5.10.120-zynqmp-fpga-generic allThe ARCH variable specifies the architecture name.
The KERNEL_SRC variable specifies the Linux Kernel source code path.
If your target system is capable of self-compiling the Linux Kernel module, you can compile it with:
shell$ make allYou need the kernel source code in /lib/modules/$(shell uname -r)/build to compile.
It can also be compiled into the Linux Kernel Source Tree.
shell$ mkdir /drivers/staging/u-dma-bufshell$ cp Kconfig Makefile u-dma-buf.c /drivers/staging/u-dma-bufshell$ diff /drivers/staging/Kconfig
:
+source "drivers/staging/u-dma-buf/Kconfig"
+shell$ diff /drivers/staging/Makefile
:
+obj-$(CONFIG_U_DMA_BUF) += u-dma-buf/For make menuconfig, set the following:
Device Drivers --->
Staging drivers --->
u-dma-buf(User space mappable DMA Buffer) --->If you write it directly in defconfig:
shell$ diff /arch/arm64/configs/xilinx_zynqmp_defconfig
:
+CONFIG_U_DMA_BUF=mLoad the u-dma-buf kernel driver using insmod. The size of a DMA buffer should be
provided as an argument as follows.
The device driver is created, and allocates a DMA buffer with the specified size.
The maximum number of DMA buffers that can be allocated using insmod is 8 (udmabuf0/1/2/3/4/5/6/7).
zynq$ insmod u-dma-buf.ko udmabuf0=1048576
u-dma-buf udmabuf0: driver version = 5.5.0
u-dma-buf udmabuf0: major number = 248
u-dma-buf udmabuf0: minor number = 0
u-dma-buf udmabuf0: phys address = 0x1e900000
u-dma-buf udmabuf0: buffer size = 1048576
u-dma-buf u-dma-buf.0: driver installed.
zynq$ ls -la /dev/udmabuf0
crw------- 1 root root 248, 0 Dec 1 09:34 /dev/udmabuf0In the above result, the device is only read/write accessible by root.
If the permission needs to be changed at the load of the kernel module,
create /etc/udev/rules.d/99-u-dma-buf.rules with the following content.
SUBSYSTEM=="u-dma-buf", GROUP="root", MODE="0666"The module can be uninstalled by the rmmod command.
zynq$ rmmod u-dma-buf
u-dma-buf u-dma-buf.0: driver removed.For details, refer to the following URL.
The u-dma-buf kernel module has the following module parameters:
| Parameter Name | Type | Default | Description |
|---|---|---|---|
| udmabuf[0-7] | ulong | 0 | u-dma-buf[0-7] buffer size |
| info_enable | int | 1 | install/uninstall infomation enable |
| dma_mask_bit | int | 32 | dma mask bit size |
| udmabuf[0-7]_bind | charp | "" | u-dma-buf[0-7] bind device name |
| bind | charp | "" | bind device name |
| quirk_mmap_mode | int | 2 or 3 | quirk mmap mode(1:off,2:on,3:auto,4:page) |
udmabuf[0-7]This parameter specifies the capacity of the u-dma-buf to be created in bytes. The number of u-dma-buf that can be created with this parameter is 8. The device name will be udmabuf[0-7]. If this parameter is 0, the u-dma-buf is not created.
info_enableThis parameter specifies whether or not detailed information about when the u-dma-buf was created should be displayed.
dma_mask_bit** Note: The value of dma-mask is system dependent. Make sure you are familiar with the meaning of dma-mask before setting. **
udmabuf[0-7]_bindThis parameter specifies the parent device of u-dma-buf[x] (x is a number from 0 to 7). If this parameter is an empty string (default value) and the bind parameter described below is an empty string (default value), u-dma-buf[x] is created as a new platform device. If this parameter is an empty string (default value) and the bind parameter described below is not an empty string, u-dma-buf[x] is created as a child device of the device indicated by the bind parameter. If this parameter is not an empty string, u-dma-buf[x] is created as a child device of the device indicated by this parameter.
The format of the string specified in this parameter is "/".
The `` is the bus name, currently pci is supported. The bus name can be omitted. If omitted, it will be the platform bus.
The `` specifies the name of the device under bus management.
For example, to designate "0000:00:15.0" under the pci bus as the parent device of udmabuf0, do the following
…bindThis parameter specifies the parent device of u-dma-buf[0-7]. If the preceding udmabuf[x]_bind is an empty string (default value) and this parameter is an empty string (default value), u-dma-buf[x] is created as a new platform device. If the preceding udmabuf[x]_bind is an empty string (default value) and this parameter is an not empty string, u-dma-buf[x] is created as a child device of the device indicated by this bind parameter.
The format of the string specified in this parameter is "/".
The `` is the bus name, currently pci is supported. The bus name can be omitted. If omitted, it will be the platform bus.
The `` specifies the name of the device under bus management.
quirk_mmap_modeThis parameter specifies the default value of quirk-mmap-mode.
quirk-mmap is described in detail below.
If this parameter is 1, quirk-mmap is prohibited.
If this parameter is 2, quirk-mmap is used.
If this parameter is 3, quirk-mmap is not used if the device has a dma-cohrent of true, and quirk-mmap is used only if dma-coherent is false.
If this parameter is 4, quirk-mmap is used in quirk-mmap-page mode.
If the architecture is ARM or ARM64, this parameter defaults to 2.
If the architecture is other than the above, this parameter defaults to 3.
In addition to the allocation via the insmod command and its arguments, DMA
buffers can be allocated by specifying the size in the device tree file.
When a device tree file contains an entry like the following, u-dma-buf will
allocate buffers and create device drivers when loaded by insmod.
udmabuf@0x00 {
compatible = "ikwzm,u-dma-buf";
device-name = "udmabuf0";
minor-number = ;
size = ;
};
zynq$ insmod u-dma-buf.ko
u-dma-buf udmabuf0: driver version = 5.5.0
u-dma-buf udmabuf0: major number = 248
u-dma-buf udmabuf0: minor number = 0
u-dma-buf udmabuf0: phys address = 0x1e900000
u-dma-buf udmabuf0: buffer size = 1048576
u-dma-buf amba:udmabuf@0x00: driver installed.
zynq$ ls -la /dev/udmabuf0
crw------- 1 root root 248, 0 Dec 1 09:34 /dev/udmabuf0The following properties can be set in the device tree.
compatiblesizeminor-numberdevice-namesync-modesync-alwayssync-offsetsync-sizesync-directiondma-coherentdma-maskquirk-mmap-offquirk-mmap-onquirk-mmap-autoquirk-mmap-pagememory-regioncompatibleThe compatible property is used to set the corresponding device driver when loading
u-dma-buf. The compatible property is mandatory. Be sure to specify compatible
property as "ikwzm,u-dma-buf" (for u-dma-buf.ko) or "ikwzm,udmabuf-0.10.a" (for udmabuf.ko).
sizeThe size property is used to set the capacity of DMA buffer in bytes.
The size property is mandatory.
udmabuf@0x00 {
compatible = "ikwzm,u-dma-buf";
size = ;
};
If you want to specify a buffer size of 4GiB or more, specify a 64bit value as follows. A 64-bit val
No open issues yet, or sync has not completed.