This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

816x/389x : PCIe and DMA

Hello. A few days ago I got this eval board (816X/389x) and I am trying to test the data throughput from a PCI card (Xilinx FPGA) to the cpu, with no success so far. What I have:

1) tools:  ti-ezsdk_dm816x-evm_5_01_01_80

2) driver:  Xilinx provided some source code for x86 linux. I built the driver within this cpu kernel. I do not have problems with writing/reading FPGA registers, using this driver, but when I set a flag in one of them that makes the FPGA to initiate a DMA, the DMA does not show that started (or concluded). This would be shown by another FPGA register.

I am not experienced with the PCI functionality, but I assumed that the kernel should take care of the DMA request by the FPGA. I may be wrong on this, though. Do I have to do something that will make the kernel to provide the DMA support? I should note here that I have built the kernel with PCI enabled (plus PCI Debugging, under the 'Bus Support' option ) and DMA Engine enabled too (with debugging, as well).  Although, I enabled the debugging options as noted above, I am not sure I could detect anything that would help me on it.

Also, is there a (relatively low)  limit on the amount of the packet transferred through DMA? I think the example I am using asks for a 4 KB packet transfer.

Any help will be appreciated.  Thanks

 

 

  • Nicholas,

    What kind of DMA transfer are you initiating from the FPGA - read from 816x DDR or write into it?

    Assuming you are reading, please ensure that the maximum read request size set in FPGA PCIe interface configuration does not exceed 256 bytes. Please refer http://processors.wiki.ti.com/index.php/DM816x_C6A816x_AM389x_PCI_Express_Root_Complex_Driver_User_Guide#Using_PCIe_Endpoint

    As for kernel's involvement, the driver for FPGA (which will be running on 816x) will take care of allocating buffers in DDR of 816x and indicating FPGA to start DMA transfer to/from them - thus host CPU is no involved during transfer (it may get an interrupt at the end of transfer indicate completion).

       Hemant

  • Thank you for your reply.  The DMA transfer should be from the FPGA to the 816x. Yes, I read somewhere about this low limit and I reduced some registers so that now the transfer should be 64 bytes, but still, I could not see the 'DMA Done' bit set on the FPGA relevant register.

    About the DMA process, yes, this is what I thought... I see inside the driver all the buffer allocations, so, what I expect is if I see the above bit set, then to do a read buffer from the driver.

     

     

  • Just an update:  It seems like I needed this instruction in the driver:

    pci_set_master(gDev);

    after the  pci_enable_device(gDev)

    (The missing instruction is probably not needed for the x86 systems, for which the original driver was written)

    Now, DMA seems to take place... I have to look into the size of the buffers.  Is 256 bytes the limit of the packet unit (TLP) or the overall DMA size transfer?

     

     

     

  • 256 bytes is the DMA size. The PCIe port on the FPGA should for the TLP out of DMA transfer.

    I am surprised that the DMA used to work without pci_set_master(). I think pci_enable_device() should not be calling pci_set_master() implicitly.

       Hemant

  • Hi again. Yes, I am surprised too about it. But the original code that came from Xilinx does not include that instruction. I have not tested it  on a PC myself, but I was told that it worked there.

    One more question:  Inside the said driver there is this ISR

     

    void XPCIe_IRQHandler(int irq, void *dev_id, struct pt_regs *regs)
    {
      // this clears the IRQ on the fpga
      XPCIe_WriteReg(18, 0x100);

    }

    which is called when the DMA is done. For now I do not do anything other than clearing the IRQ bit on the fpga side so that it will not trigger continuous interrupts. However, I get this message by the kernel:

    irq event 48: bogus return value 12

    followed by : backtrace and a few other messages related to backtrace, I gather.

    Any idea what it means?  

    Thanks

     

     

  • Hi again.... Never mind this last question (irq event 48.. etc)...  Resolved.

    Thanks for all the help... I am sure I will need a bot more later on when I do more work on it.

     

     

  • Hi Nicholas,

    Can you tell me how you fixed the issue: (irq event 48.. etc)? (also with the DMA driver from Xilinx, I work on CentOS 6)

    I get the same thing.

    Thanks, raphael

  • Well, I do not recall all the details now, because I tried/tested too many things back then. But here is the IRQ ISR inside the fpga driver

    static irqreturn_t XPCIe_IRQHandler(int irq, void *dev_id, struct pt_regs *regs)

    Note it is not "void ..."

    then inside this isr:

    irqreturn_t   handled=IRQ_NONE; // = 0

    if (my_interrupt)    // if this interrupt comes from your fpga ... some registers will show that

    {

        ...................   // do here whatever you want to do for the interrupt

        handled = IRQ_HANDLED;  // =1

    }

    return(handled);

  • Thanks Nicholas,

    I actually also fixed the problem...

    In case anyone is interested:

    I changed the flags SHARED and SAMPLE_RANDOM when requesting the IRQ as mentioned in the driver:

     // In past architectures, the SHARED and SAMPLE_RANDOM flags were called: SA_SHIRQ and SA_SAMPLE_RANDOM
    // respectively. In older Fedora core installations, the request arguments may need to be reverted back.
    // SA_SHIRQ | SA_SAMPLE_RANDOM
    printk(KERN_INFO"%s: ISR Setup..\n", gDrvrName);
    if (0 > request_irq(gIrq, &XPCIe_IRQHandler, IRQF_SHARED | IRQF_SAMPLE_RANDOM, gDrvrName, gDev)) {
    printk(KERN_WARNING"%s: Init: Unable to allocate IRQ",gDrvrName);
    return (CRIT_ERR);
    }
    
    
    Cheers,
    raph
  • Hi Raphael. I do not recall changing anything in that part of the code. However, what you wrote is exactly what is in the driver I got from Xilinx. Probably, you had an earlier version of it. Anyway, since your problem is solved, all is well. Good luck with the rest of your work.