bperez77 / xilinx_axidma

A zero-copy Linux driver and a userspace interface library for Xilinx's AXI DMA and VDMA IP blocks. These serve as bridges for communication between the processing system and FPGA programmable logic fabric, through one of the DMA ports on the Zynq processing system. Distributed under the MIT License.
MIT License
459 stars 228 forks source link

Add Multi-Channel DMA Support #7

Open bperez77 opened 8 years ago

bperez77 commented 8 years ago

The Zynq processing system has a limited number of DMA channels, so sharing the channel between multiple agents can be useful, if they have low bandwidth requirements.

corna commented 6 years ago

Hi.

I'm trying to implement the multi-channel support, but I'm having some problems. I'm using this DT:

[...]
amba_pl: amba_pl {
    #address-cells = <1>;
    #size-cells = <1>;
    compatible = "simple-bus";
    ranges ;
    axi_dma_0: dma@40400000 {
        #dma-cells = <1>;
        clock-names = "s_axi_lite_aclk", "m_axi_sg_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk";
        clocks = <&clkc 15>, <&clkc 15>, <&clkc 15>, <&clkc 15>;
        compatible = "xlnx,axi-dma-1.00.a";
        interrupt-parent = <&intc>;
        interrupts = <0 29 4 0 30 4>;
        reg = <0x40400000 0x10000>;
        xlnx,addrwidth = <0x20>;
        xlnx,include-sg ;
        xlnx,mcdma ;
        dma-channel@40400000 {
            compatible = "xlnx,axi-dma-mm2s-channel";
            dma-channels = <0x2>;
            interrupts = <0 29 4>;
            xlnx,datawidth = <0x20>;
            xlnx,device-id = <0x0>;
        };
        dma-channel@40400030 {
            compatible = "xlnx,axi-dma-s2mm-channel";
            dma-channels = <0x1>;
            interrupts = <0 30 4>;
            xlnx,datawidth = <0x20>;
            xlnx,device-id = <0x1>;
        };
    };

    axidma_chrdev: axidma_chrdev@0 {
        compatible = "xlnx,axidma-chrdev";
        dmas = <&axi_dma_0 0 &axi_dma_0 1 &axi_dma_0 2>;
        dma-names = "tx0", "tx1", "rx0";
    };
};
[...]

With some tweaks in the code I am able to get the three DMA channels in dma_request_slave_channel, however the read/write operations always time out.

As suggested on various threads, the structure is AXI DMA -> AXIS interconnect -> multiple devices (see the full BD here).

I've also tried with a simple module written from scratch: without the multi-channel both the reads and the writes work but, when I enable the multi-channel and add the interconnect and the two slaves, it only times out.

Any idea?

bperez77 commented 6 years ago

Yeah, as you found out, I haven't yet had a chance to add MCDMA support yet to the driver. Can you post the changes you've made to the driver on this thread? I can take a look over and see what the issue might be.

I'm not sure where you made all the changes, but if I had to guess, I'd imagine there's something in axidma_prep_transfer that needs to be changed.

corna commented 6 years ago

I'm working on a test scratch module right now, I haven't modified this driver yet.

It partially works now, I've found that the MCDMA works only with dmaengine_prep_interleaved_dma and not with dmaengine_prep_slave_sg. The main problem is related to the IRQs: the AXIDMA IP core has only two interrupt lines but the Xilinx DMA IRQ handler doesn't demultiplex the interrupt and always completes the descriptor of the first called handler (which should be the first registered).

I've modified xilinx_dma.c adding the correct demultiplexing and the TX seems to work now but the RX doesn't work yet.

I see that Xilinx has recently released (2017.3) a dedicated AXI MCDMA module with dedicated interrupt lines however, even if they claim they have Linux drivers, I haven't found any matching driver in their repository. I'll try to contact them and ask for more informations.

bperez77 commented 6 years ago

Sorry for the late reply, I missed the notification. I see, yeah things get more complicated with the IRQs because of the multiple channels. It doesn't surprise me they don't have it up yet for their backend driver; I faced similar issues with other features when I first started the driver. It's definitely not uncommon for Xilinx to overpromise and underdeliver.

It's interesting that the TX works properly but the RX times out. I'm guessing you're trying this with a simple loopback example? I can't see a reason why the RX wouldn't work.

corna commented 6 years ago

According to the DMA doc all the channels must be configured before the data comes in. This complicates things, as we would need an extra reset line to keep the interconnects disabled (but not the DMA engine) until the DMA is fully configured.

For now I'm using multiple DMA controllers, maybe in the future I'll try again to make it work.

samberhanu commented 3 years ago

According to the DMA doc all the channels must be configured before the data comes in. This complicates things, as we would need an extra reset line to keep the interconnects disabled (but not the DMA engine) until the DMA is fully configured.

For now I'm using multiple DMA controllers, maybe in the future I'll try again to make it work.

Corna, can you please do a quick write up on how to compile your code? I am running into issue of copy_to_user not being available