Как найти подробную информацию о причине сбоя dma_request_chan()?
Во внешнем модуле ядра, используя DMA Engine, при вызове dma_request_chan()
возвращает указатель ошибки со значением -19, то есть ENODEV или "Нет такого устройства". Теперь в активном дереве устройств я действительно нахожу запись dma-names с тем, для чего я пытаюсь получить канал, поэтому я подозреваю, что что-то еще глубже в лесу уже не найдено.
Как мне узнать, что случилось?
Задний план:
У меня есть плата Zynq MP Ultrascale+ с дизайном FPGA, который использует блок AXI VDMA для предоставления одного канала данных, которые должны быть получены в Linux Cortex A, где данные записываются в DDR4 с помощью FPGA и читаются из Linux.
Я обнаружил, что есть драйвер Xilinx DMA, включенный в ядро, в любом случае в репозитории исходного кода Xilinx, в настоящее время версия ядра 5.6.0. И что у этого драйвера нет интерфейса пользовательского пространства, поэтому требуется промежуточный драйвер ядра.
Это изображено, и у них есть пример здесь: Раздел "4 Проектирование прокси DMA". Я изменил код в dma-proxy.c связанного с ним zip-файла таким образом, что он использует только канал RX, то есть пытается только запросить его.
Код для этого здесь, чтобы не делать этот пост огромным:измененный dma-proxy.c на 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
Похоже, мой 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 Engine "зондировал", что означает, что драйвер самого низкого уровня загружен и готов, верно?
Мне кажется, что там должно быть мое устройство, но ядро не соглашается.
1 ответ
У меня такая же проблема с аналогичной конфигурацией. Покопавшись в большом количестве исходного кода ядра (особенно в драйверах / dma / xilinx / xilinx_dma.c), я решил эту проблему, изменив номер канала в
dmas
параметр от 0 до 1 в записи дерева устройств dma-proxy следующим образом:
dma_proxy {
compatible ="xlnx,dma_proxy";
dmas = <&axi_dma_0 1>;
dma-names = "dma_proxy_rx";
};
Похоже, что пример dma-proxy написан для блока AXI DMA с каналами mm2s (канал №0) и s2mm (канал №1). И если мы удалим канал mm2s из блока AXI DMA, канал s2mm останется №1.