Re: ezdma: Simple read()/write() userspace interface for dmaengine.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Jeremy,

On Thu, May 21, 2015 at 09:34:03PM -0400, Jeremy Trimble wrote:
> Hello all,
> 
> I've written a kernel module that allows data to be sent to or received from
> any DMA device that supports the dmaengine API, using simple read()/write()
> calls from userspace.
> 
> Motivation:
> 
> While doing some work for my master's thesis recently using the Xilinx Zynq
> SoC, I needed a way to stream test data into and out of an FPGA soft-core I was
> developing.  I was using the Xilinx AXI DMA soft-core (and its
> dmaengine-compatible driver that I believe is related to Kedareswara rao
> Appana's patch submitted recently).
> 
> Although dmaengine provides a versatile in-kernel API, to my knowledge there's
> no direct userspace interface for the case where one wants to simply
> send/receive data through a slave dma channel -- writing a separate
> userspace-facing module would be required.  (Or some hack using /dev/kmem.)

Good.

I'd have some usage for that as well, mostly to support the async_tx
transfers types though, and offload them from the CPU.

> Usage:
> 
> The ezdma ("easy DMA") module implements a read()/write() interface for
> receiving/sending data through any slave DMA channel.
> 
> It is configured using the device tree:
> 
> 1. Include a node like below into the device tree:
> 
> ezdma0 {
>     compatible = "ezdma";
>     dmas = <&loopback_dma 0 &loopback_dma 1>;
>     dma-names = "loop_tx", "loop_rx";
>     ezdma,dirs = <2 1>;     // direction of DMA channel:
>                             //   1 = RX (dev->cpu), 2 = TX (cpu->dev)
> };
> 
> 2.  After inserting the ezdma module, two devices, as named in your dma-names
> above, will become available:
> 
>     /dev/loop_tx
>     /dev/loop_rx

Even though I understand that this is the most convenient setup right
now, I would expect to have this a bit more dynamic, and be able to
request/release channels straight from the user-space (to have several
memset happening at the same time for example).

That would probably require a different interface though, or at least
to implement some ioctls.

> 3. Sending data is as easy as:
> 
>     int tx_fd = open("/dev/loop_tx", O_WRONLY);
>     int rx_fd = open("/dev/loop_rx", O_RDONLY);
> 
>     write(tx_fd, tx_buf, xfer_size);    // send a DMA transaction
>     read (rx_fd, rx_buf, xfer_size);
> 
> Currently, each read()/write() call causes a single transfer to occur in the
> underlying slave DMA channel, but support could be added for readv()/writev()
> as well.

How do you set the address it should be sent to? the width? burst? Is
it currently hardcoded (which is totally fine for your use case, but
wouldn't really work for other use).

This is definitely a good start though.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

Attachment: signature.asc
Description: Digital signature


[Index of Archives]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux PCI]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux