2014-02-07 76 views
0

我正在开发Xilinx Virtex 6 PCIe定制板卡的设备驱动程序。 在做DMA写(从主机到设备)会出现以下情况:Linux设备驱动程序DMA内存缓冲区未按PCIe硬件顺序排列

用户空间应用:

a. fill buffer with the following byte pattern (tested up to 16kB) 
    00 00 .. 00 (64bytes) 
    01 01 .. 00 (64bytes) 
    ... 
    ff ff .. ff (64bytes) 
    00 00 .. 00 (64bytes) 
    01 01 .. 00 (64bytes) 
    etc 

b. call custom ioctl to pass pointer to buffer and size 

内核空间:

a. retrieve buffer (bufp) with 
    copy_from_user(ptdev->kbuf, bufp, cnt) 
b. setup and start DMA 
    b1. //setup physical address 
     iowrite32(cpu_to_be32((u32) ptdev->kbuf_dma_addr), 
      ptdev->region0 + TDO_DMA_HOST_ADDR); 
    b2. //setup transfer size 
     iowrite32(cpu_to_be32(((cnt+3)/4)*4), 
      ptdev->region0 + TDO_DMA_BYTELEN); 
    b3. //memory barrier to make sure kbuf is in memorry 
     mb(); 
    //start dma 
    b4. iowrite32(cpu_to_be32(TDO_DMA_H2A | TDO_DMA_BURST_FIXED | TDO_DMA_START), 
       ptdev->region0 + TDO_DMA_CTL_STAT); 
c. put process to sleep 
    wait_res = wait_event_interruptible_timeout(ptdev->dma_queue, 
          !(tdo_dma_busy(ptdev, &dma_stat)), 
          timeout); 
d. check wait_res result and dma status register and return 

Note that the kernel buffer is allocated once at device probe with: 
ptdev->kbuf = pci_alloc_consistent(dev, ptdev->kbuf_size, --512kB 
           &ptdev->kbuf_dma_addr); 

设备PCIE TLP转储(通过逻辑分析仪获得在Xilinx核心之后):

a. TLP received (by the device) 
a1. 40000001 0000000F F7C04808 37900000 (MWr corresponds to b1 above) 
a1. 40000001 0000000F F7C0480C 00000FF8 (MWr corresponds to b2 above) 
a1. 40000001 0000000F F7C04800 00010011 (MWr corresponds to b4 above) 

b. TLP sent (by the device) 
b1. 00000080 010000FF 37900000 (MRd 80h DW @ addr 37900000h) 
b2. 00000080 010000FF 37900200 (MRd 80h DW @ addr 37900200h) 
b3. 00000080 010000FF 37900400 (MRd 80h DW @ addr 37900400h) 
b4. 00000080 010000FF 37900600 (MRd 80h DW @ addr 37900600h) 
... 

c. TLP received (by the device) 
c1. 4A000020 00000080 01000000 00 00 .. 00 01 01 .. 01 CplD 128B 
c2. 4A000020 00000080 01000000 02 02 .. 02 03 03 .. 03 CplD 128B 
c3. 4A000020 00000080 01000000 04 04 .. 04 05 05 .. 05 CplD 128B 
c4. 4A000020 00000080 01000000 06 06 .. 0A 0A 0A .. 0A CplD 128B <= 
c5. 4A000010 00000040 01000040 07 07 .. 07    CplD 64B <= 
c6. 4A000010 00000040 01000040 0B 0B .. 0B    CplD 64B <= 
c7. 4A000020 00000080 01000000 08 08 .. 08 09 09 .. 09 CplD 128B <= 
c8. 4A000020 00000080 01000000 0C 0C .. 0C 0D 0D .. 0D CplD 128B 
.. the remaining bytes are transfered correctly and 
the total number of bytes (FF8h) matches the requested size 
signal interrupt 

现在这个表面存储器命令er ror发生的概率很高(0.8 < p < 1),并且排序不匹配发生在传输中不同的随机点。

编辑:请注意,上述点c4将表明内存驱动程序没有按正确顺序填充内存(我假设内存控制器使用连续内存填充TLP)。 64B是缓存行的大小,这可能与缓存操作有关。

当我禁用与内核缓冲区高速缓存,

echo "base=0xaf180000 size=0x00008000 type=uncachable" > /proc/mtrr 

错误仍然发生,但更多的很少(P < 0.1和依赖于传输大小)

这只是发生在一个i7-基于4770(Haswell)的机器(在3台相同的机器上进行测试,配有3块板)。 我尝试了内核2.6.32(RH6.5),库存3.10.28和库存3.13.1,结果相同。

我在基于i7-610 QM57的机器和Xeon 5400机器上尝试了代码和设备,没有出现任何问题。

欢迎任何想法/建议。

此致

克劳迪奥

回答

0

QM57支持PCIe 2.0

而我想象i7-4770机的主板支持PCIe 3.0

我怀疑有可能是一种的PCIe 3.0主板和您的V6设备之间的协商失败的(的PCIe 2.0,太)

+0

感谢您的回答。 'lspci'为我提供以下内容:
'LnkSta:速度2.5GT/s,宽度x8,TrErr-列车 - SlotClk- DLActive- BWMgmt- ABWMgmt-。 '
它看起来与PCIe 2.0(2.5GT/s)链接相关联。 – Claudio

+2

我记得PCIe支持TLP的重新排序,如果扩展位打开的话。它是'pci_regs.h'中的'PCI_EXP_DEVCTL_RELAX_EN'。你能检查这是否与你的问题有关吗? *比较* https://github.com/torvalds/linux/blob/master/drivers/net/ethernet/broadcom/tg3.c#L9132 – nodakai

+0

@nodaki。事实上,TLP具有与排序和缓存一致性相关的属性(2位)。这些是TLP头的字节2中的比特5:4。 位5:松散排序位(如果1允许松散排序,如果0使用严格的排序) 位4:无侦测位(如果如果0窥探启用在此访问1个禁用探听) 在B [1 ,2,3,...]我的设计发送 00000080:MRd TC = 0 EP = 0 TD = 0 Attr = 0 Len = 0x80 DW(256Bytes注意= MaxReadRequest) 不过,我按照您的建议清除了PCI_EXP_DEVCTL_RELAX_EN没有明显的变化。 – Claudio

1

我知道这是一个古老的线程,但对于原因“错误”是完成重新排序。多个未完成的读取请求不必按顺序回答。完成只是为了相同的请求。 最重要的是:总是有相同的标签分配给请求,如果请求同时处于活动状态,这是非法的。

1

在提供的示例中,所有MemRd TLP具有相同的TAG。当您没有收到与此TAG相对应的最后一个CplD时,您不能使用相同的TAG。因此,如果您发送MemRd,请等待,直到您获得具有此标记的CplD并再次触发MemRd,您的所有数据将按顺序排列(但在这种情况下,总线使用率会很低,并且无法获得高带宽占用)。

也读这个pci_alloc_consistent uncached memory。它不喜欢你的平台上的缓存问题。我会更好地调试设备内核。

相关问题