我正在使用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之后刷新写入队列?
我在这里做错了什么?
答案 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设备。