我如何使用memcpy_toio / fromio?

时间:2015-02-14 17:41:48

标签: c linux-kernel memcpy

我正在使用C中的内核模块与PCIe卡通信,并且我使用pci_iomap分配了一些io内存,并使用ioread / write32在那里写/读。

这有效,但性能很差,我读过我可以通过memcpy_toio / fromio使用块传输,而不是一次只做32b。

要写,我正在使用iowrite32(buffer[i], privdata->registers + i);

要阅读,我会buffer[i] = ioread32(&privdata->registers[i]);

我尝试用以下内容替换for循环:

memcpy_toio(privdata->registers, buffer, 2048);
memcpy_fromio(buffer, privdata->registers, 2048);

如果我只用memcpy_toio替换写循环并使用ioread32进行读取,程序不会崩溃,但指令似乎没有做任何事情(寄存器不会改变) ;

另外,当我用memcpy_fromio指令替换read循环时,它会崩溃。

我在想这可能是因为读取尝试在仍然被写入时访问mem位置。有没有办法在iowrite32或memcpy_toio之后刷新写入队列?

我在这里做错了什么?

2 个答案:

答案 0 :(得分:2)

memcpy_from/toio()只有在I / O内存的行为类似于内存时才能使用,即,如果值可以推测性地读取,并且可以多次写入或者不按顺序写入。

标记为不可预取的I / O范围不支持此功能。

答案 1 :(得分:1)

您使用哪种缓冲区类型?

查看memcpy_fromio()memcpy_toio()

的实施情况
 static inline void
 memcpy_fromio(void *dst, volatile void __iomem *src, int count)
 {
        memcpy(dst, (void __force *) src, count);
 }

 static inline void
 memcpy_toio(volatile void __iomem *dst, const void *src, int count)
 {
         memcpy((void __force *) dst, src, count);
 }

哟可以看到简单的memcpy电话。

查看iowrite32()ioread32()实施:

static inline void iowrite32(u32 val, void __iomem *p)
 {
         if (__is_PCI_addr(p))
                 val = _swapl(val);
         __builtin_write32(p, val);
         if (__is_PCI_MEM(p))
                 __flush_PCI_writes();
 }

 static inline unsigned int ioread32(void __iomem *p)
 {
         uint32_t ret = __builtin_read32(p);
         if (__is_PCI_addr(p))
                 ret = _swapl(ret);
         return ret;
 }

如您所见memcpy_fromio()memcpy_toio()不适合使用PCIe设备。