linux-kernel - 如何查找 dma_request_chan() 失败原因详细信息?

标签 linux-kernel linux-device-driver embedded-linux xilinx zynq-ultrascale+

在外部内核模块中,使用DMA引擎,调用dma_request_chan()时返回值为 -19 的错误指针,即 ENODEV 或“没有这样的设备”。 现在,在事件设备树中,我确实找到了一个 dma-names 条目,其中包含我试图获取 channel 的内容,因此我怀疑森林中更深处的其他内容尚未找到.

如何找出问题所在?

背景:

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

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

这是描述的,他们在这里有一个例子:Section "4 DMA Proxy Design" 。我修改了链接的 zip 文件的 dma-proxy.c 中的代码,使其仅使用 RX channel ,即也仅尝试请求它。

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

  • 第 407 行的功能为 create_channel() ,曾经使用 dma_request_slave_channel()它放弃了它所包装的函数的错误代码,因此为了查看错误,我使用了它: dma_request_chan() .
  • 函数create_channel()在函数 dma_proxy_probe() 中调用@ 第 470 行(之前发生的事件被编译开关停用)。
  • 通过这次通话,dma_request_chan()将使用以下参数调用:

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

我的主板的设备树为 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

看起来我正在尝试请求 channel 的 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 引擎被“探测”,这意味着最低级别的驱动程序已加载并准备就绪,对吗?

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

最佳答案

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

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

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

关于linux-kernel - 如何查找 dma_request_chan() 失败原因详细信息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61659987/

相关文章:

linux - 我在哪里可以获得 x86 的 32 位 Linux 内核源代码

基于 Linux 构建的 Android 内核

使用字符设备驱动程序捕获信号和暂停

linux - 嵌入式 linux 设备上的 USB 驱动程序测试

linux - 构建 busybox,包括内核头文件、要包含哪些文件

linux - Linux 中 tcpip 堆栈的多个实例

linux - 学习网络驱动程序接口(interface)的好链接

c - 尝试从 TLS 数据包中提取 SNI 时出现 BPF 验证错误

linux - 如何强制 iscsid 重新连接目标?

c - Linux Kernel 在哪里锁定和解锁信号量?