Linux kernel Linux PCI驱动程序读取整合

Linux kernel Linux PCI驱动程序读取整合,linux-kernel,linux-device-driver,embedded-linux,fpga,pci,Linux Kernel,Linux Device Driver,Embedded Linux,Fpga,Pci,我有一个与FPGA通信的PCI驱动程序。如果可以避免的话,我尽量不把DMA放在FPGA上,我感觉非常接近我想要的:突发读/写速度>20MB/s 我的设计只使用了一个条,我用ioremap_wc()映射了它,这使得我的写入速度最高达到了~200MB/s,这是我的FPGA支持的最快速度。但是,我的读取速度只有~7MB/s。这两个基准测试都是8KB 我的问题是:我是否缺少一个可以提高我的读取速度的LinuxAPI调用,或者我必须实现DMA才能获得比上面所示更好的性能 我的驱动程序运行在ARM 64位处

我有一个与FPGA通信的PCI驱动程序。如果可以避免的话,我尽量不把DMA放在FPGA上,我感觉非常接近我想要的:突发读/写速度>20MB/s

我的设计只使用了一个条,我用
ioremap_wc()
映射了它,这使得我的写入速度最高达到了~200MB/s,这是我的FPGA支持的最快速度。但是,我的读取速度只有~7MB/s。这两个基准测试都是8KB

我的问题是:我是否缺少一个可以提高我的读取速度的LinuxAPI调用,或者我必须实现DMA才能获得比上面所示更好的性能

我的驱动程序运行在ARM 64位处理器上:NXP iMX8

编辑:

我在用户空间中映射我的条,以与FPGA的寄存器接口。这样做时,我必须禁用缓存,因为在读取条偏移量时,我不会总是在条偏移量中看到正确的数据

编辑2: 下面是我的实现的一些简化代码片段(希望它们能有所帮助)

我的驱动程序的
\u read()
功能:

ssize_t driver_read(struct file *filp,
                     char __user *userBuf,
                     size_t len,
                     loff_t *offp)
{
...

    if (copy_to_user(userBuf, BAR.kvm_addr + *offp, len) != 0)
        return (-EFAULT);

    return (len);
}
我的酒吧地图:

ioremap_wc(pBAR->pci_start, // PCI bus start address
           pBAR->len);      // BAR size
我对用于测试的
pread()
的调用

...
int fd = open("/path/to/driver", O_RDWR, 0666);
uint32_t *rxBuf = (uint32_t *)malloc(4 * 2048);
memset(rxBuf, 0x00, 4 * 2048);

pread(fd,
      rxBuf,
      4 * 2048,
      0);
...

您使用什么指令读取设备?每个读取操作都需要到设备的往返路径,因此,如果执行1字节或4字节读取,则所需时间比使用8、32或64字节读取要长得多。我在用户空间中使用
pread()
,我的驱动程序使用
copy\u to\u user()
在它的读取文件操作中完成了繁重的工作。我认为@prl是在问你用什么来读取设备内存(例如
readb
readw
,readl
ioread8
ioread16
ioread32`或其他),而不是你用什么来访问用户内存。我对ARM一无所知。在x86上,我会尝试使用AVX512获得64字节的加载。或MOVDIR64B(尽管其具有特殊的行为,可能会使其变得更糟)。这两者的可用性都有限,因此32字节AVX可能更实用。PCIe最多支持512字节传输,因此DMA确实是您想要的。