首页 > 解决方案 > 如何查找 dma_request_chan() 失败原因详情?

问题描述

在外部内核模块中,使用 DMA 引擎,调用时dma_request_chan()返回值 -19 的错误指针,即ENODEV或“No such device”。现在,在活动设备树中,我确实找到了一个dma-names条目,其中包含我试图为其获取通道的内容,所以我怀疑森林深处的其他东西已经找不到了。

我如何找出问题所在?

背景:

我这里有一块 Zynq MP Ultrascale+ 板,其 FPGA 设计使用 AXI VDMA 块提供一个数据通道,以便在 Cortex A 的 Linux 上接收,其中数据由 FPGA 写入 DDR4 并从 Linux 读取。

我发现内核中有一个 Xilinx DMA 驱动程序,无论如何在 Xilinx 源代码库中,当前内核版本为 5.6.0。并且该驱动程序没有用户空间接口,因此需要一个中间内核驱动程序。

对此进行了描述,他们在这里有一个示例:“4 DMA 代理设计”部分。我修改了此处链接的 zip 文件的dma-proxy.c中的代码,使其仅使用 RX 通道,即也仅尝试请求它。

代码在这里,为了不让这篇文章变得庞大: 修改了 onlinegdb.com 上的dma- proxy.c

我的开发板的设备树添加了 dma-proxy 驱动程序节点,如dma-proxy.c顶部所示

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

名称“axi_dma_0”与 axi DMA 设备树节点中的名称匹配:

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>;
    };

如果我现在看这里:

% cat /proc/device-tree/dma_proxy/dma-names
dma_proxy_rx

看起来我正在尝试请求频道的dma_proxy_rx在那里。

编辑:在引导日志中,我看到:

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!!

有警告 - 但最终,Xilinx AXI DMA 引擎得到了“探测”,这意味着最低级别的驱动程序已加载并准备就绪,对吗?

所以在我看来应该有我的设备,但内核不同意。

标签: linux-kernellinux-device-driverembedded-linuxxilinxzynq-ultrascale+

解决方案


类似的配置我也有同样的问题。在挖掘了大量内核源代码(尤其是驱动程序/dma/xilinx/xilinx_dma.c)后,我通过dmas在 dma-proxy 设备树条目中将参数中的通道号从 0 更改为 1 解决了这个问题,如下所示:

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

似乎 dma-proxy 示例是为具有 mm2s(通道 #0)和 s2mm(通道 #1)通道的 AXI DMA 块编写的。如果我们从 AXI DMA 块中删除 mm2s 通道,s2mm 通道将保持 #1。


推荐阅读