cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
sktpin
Adventurer
Adventurer
785 Views
Registered: ‎09-11-2018

ENODEV on requesting AXI DMA channel

Jump to solution

In an external kernel module, using DMA Engine, when calling dma_request_chan returns an error pointer of value -19, i.e. ENODEV or "No such device".
Now, in the active device tree, I do find a dma-names entry with what I'm trying to get a channel for, so my suspicion is that something else deeper in the forest is already not found.

How do I find out what's wrong?

Background:

I have a Zynq MP Ultrascale+ board here, with an FPGA design which uses AXI VDMA block to provide one channel of data to be received on the Cortex A's Linux, where the data is written to DDR4 by the FPGA and to be read from Linux.

I found that there is a Xilinx DMA driver included in the kernel, in the Xilinx source repo anyway, currently kernel version 5.6.0.
And that that driver has no userspace interface, such that an intermediate kernel driver is needed.

This is depicted, and they have an example here: Section "4 DMA Proxy Design" 
I modified the code in the dma-proxy.c of the zip file linked there such that it uses only the RX channel, i.e. also only tries to request it.

The code for that is here, to not make this post huge: Modified dma-proxy.c at onlinegdb.com

  • Line 407 has the function create_channel, which used to use dma_request_slave_channel which ditches the error code of the function it wraps, so to see the error, I am using that one instead: dma_request_chan.
  • The function create_channel is called in function dma_proxy_probe @ line 470 (the occurences before that are deactivated by compile switch).
  • So by way of this call, dma_request_chan will be called with the parameters:

    • create_channel(pdev, &channels[RX_CHANNEL], "dma_proxy_rx", DMA_DEV_TO_MEM);

The Device Tree for my board has an added node for dma-proxy driver as is shown at the top of the dma-proxy.c

dma_proxy {
compatible ="xlnx,dma_proxy";
dmas = <&axi_dma_0 0>;
dma-names = "dma_proxy_rx";
};


The name "axi_dma_0" matches with the name in the axi DMA device tree node:

axi_dma_0: dma@a0000000 {
#dma-cells = <0x1>;
clock-names = "s_axi_lite_aclk", "m_axi_s2mm_aclk";
clocks = <0x3 0x47 0x3 0x47>;
compatible = "xlnx,axi-dma-7.1", "xlnx,axi-dma-1.00.a";
interrupt-names = "s2mm_introut";
interrupt-parent = <0x1d>;
interrupts = <0x0 0x2>;
reg = <0x0 0xa0000000 0x0 0x1000>;
xlnx,addrwidth = <0x28>;
xlnx,sg-length-width = <0x1a>;
phandle = <0x1e>;

dma-channel@a0000030 {
compatible = "xlnx,axi-dma-s2mm-channel";
dma-channels = <0x1>;
interrupts = <0x0 0x2>;
xlnx,datawidth = <0x40>;
xlnx,device-id = <0x0>;
};


If I now look here:

cat /proc/device-tree/dma_proxy/dma-names
It yields exactly this string: dma_proxy_rx
Looks like my dma_proxy_rx, that I'm trying to request the channel for, is in there.

In the boot log, I see this:

xilinx-vdma a0000000.dma: Please ensure that IP supports buffer length > 23 bits
irq: no irq domain found for interrupt-controller@a0010000 !
xilinx-vdma a0000000.dma: unable to request IRQ 0
xilinx-vdma a0000000.dma: WARN: Device release is not defined so it is not safe to unbind this driver while in use
xilinx-vdma a0000000.dma: Xilinx AXI DMA Engine Driver Probed!!

There are warnings - but in the end, the Xilinx AXI DMA Engine got "probed", meaning the lowest level driver loaded and is ready, right?

So it looks to me like there should be my device, but the kernel disagrees.

0 Kudos
1 Solution

Accepted Solutions
sktpin
Adventurer
Adventurer
664 Views
Registered: ‎09-11-2018

Ok, apparently it's easy to get confused when making "live" changes to FPGA which Linux does not like but doesn't tell me about, but stuff doesn't work anymore (as expected) and my mental model of what is happening / should happen is off. Then sometimes rmmod...insmod sequence (soft version of "have you tried turning it off and on again?") helps...
I got  data from the traffic generator feeding the DMA, and the real data source didn't work at first because of another thing missing in the FPGA.

I guess I'll close off this thread now by saying the problem of the original question was due to a combination of FPGA / device tree configuration issues.
I would have liked, though, to hear about tools or methods to analyze such errors from the Linux side, which is not the way the errors were discovered here (well, in some way, on a high level).

View solution in original post

0 Kudos
4 Replies
sktpin
Adventurer
Adventurer
706 Views
Registered: ‎09-11-2018

Ok, sees the kernel message of the Axi DMA driver claiming "probed!!" is a lie, it fails after that line in the code. Apparently didn't like an extra interrupt controller in the FPGA, the HW guy said, it was removed. A TX channel with loopback was added just be be closer to the original driver example.
Also, now using kernel 4.19.0 from the xlnx repo, not the 5.6.0-rc1 anymore.

After loading the  dma-proxy.ko module, the TX and RX devices were under /dev as they should be.

Running the userspace test program that accompanies the dma-proxy code yields "DMA timed out" in the kernel messages, though. No idea yet why.

Seeing this status of the AXI DMA IP block read out with a script:

DMA status register:
  DMA channel halted
  DMA in scatter Gather mode
DMA control register:
  DMA channel stop


Hrm. Looks like it's not being started...

Happening here in the driver:

static void wait_for_transfer(struct dma_proxy_channel *pchannel_p)
{
	unsigned long timeout = msecs_to_jiffies(3000);
	enum dma_status status;

	pchannel_p->interface_p->status = PROXY_BUSY;

	/* Wait for the transaction to complete, or timeout, or get an error
	 */
	timeout = wait_for_completion_timeout(&pchannel_p->cmp, timeout);
	status = dma_async_is_tx_complete(pchannel_p->channel_p, pchannel_p->cookie, NULL, NULL);

	if (timeout == 0)  {
		pchannel_p->interface_p->status  = PROXY_TIMEOUT;
		printk(KERN_ERR "DMA timed out\n");
	} else if (status != DMA_COMPLETE) {
		pchannel_p->interface_p->status = PROXY_ERROR;
		printk(KERN_ERR "DMA returned completion callback status of: %s\n",
			   status == DMA_ERROR ? "error" : "in progress");
	} else
		pchannel_p->interface_p->status = PROXY_NO_ERROR;
}

 

0 Kudos
sktpin
Adventurer
Adventurer
693 Views
Registered: ‎09-11-2018

Ok, never mind the last post, there was a version mismatch between things and the seen behavior an artifact of that...

What I am now getting is this:
Basically, the loopback test works with the dma-proxy driver example.

If I now change the data source i the FPGA from looped-back TX channel to the real source, and start the sending of data,
and change the usermode example (dma-proxy-test.c) such that it does not create the TX thread, but only tries to initiate RX transfers, then I get "DMA timed out" from the driver in the kernel messages.

So it seems, what ever the DMA engine is waiting for - it must be more than just data flowing. It's visible in Vivado that the FPGA is doing its data sending.
But I don't understand enough details of this driver stuff / Linux dmaengine.

Can someone tell whether the error here could be that the dmaengine is waiting for other conditions, which were met when the TX loopback was used, but now, not anymore?
That would be my guess. But not sure where to look.

0 Kudos
sktpin
Adventurer
Adventurer
665 Views
Registered: ‎09-11-2018

Ok, apparently it's easy to get confused when making "live" changes to FPGA which Linux does not like but doesn't tell me about, but stuff doesn't work anymore (as expected) and my mental model of what is happening / should happen is off. Then sometimes rmmod...insmod sequence (soft version of "have you tried turning it off and on again?") helps...
I got  data from the traffic generator feeding the DMA, and the real data source didn't work at first because of another thing missing in the FPGA.

I guess I'll close off this thread now by saying the problem of the original question was due to a combination of FPGA / device tree configuration issues.
I would have liked, though, to hear about tools or methods to analyze such errors from the Linux side, which is not the way the errors were discovered here (well, in some way, on a high level).

View solution in original post

0 Kudos
lauziepi
Adventurer
Adventurer
92 Views
Registered: ‎04-06-2012

Hello!

I know this thread is old and you have circumvented your issue by going back to kernel 4.19, but I encountered the same problem when upgrading from kernel 4.19 to 5.4. Since I stumbled here when searching google about this, I figured I'd post additional info that does not require using an older kenel.

 

Your DMA channel is S2MM (rx from the Linux point of view), but you have used the channel ID for tx channels. On the 4.19 kernel, dma_request_slave_channel would still work even on a DMA channel that had been defined as M2SS (tx) in the devicetree. However, the 5.4 kernel function call fails because it expects the name AND a proper RX channel ID. In my situation, my DMA driver was working fine on 4.19 but the 5.4 upgrade broke it. I suspect this is why your driver works fine on the older 4.19 kernel.

The information regarding channel IDs can be found here, where it is written that 0 is for M2SS (tx) and 1 is for SS2M (rx): https://github.com/Xilinx/linux-xlnx/blob/master/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt

 

Thus, to fix your initial issue properly, you would have to change the dmas line of your dma_proxy node from <&axi_dma_0 0> to <&axi_dma_0 1>.

 

0 Kudos