PCIE 使用生产者/消费者订购模型,但 AXI4 使用不同的订购模型。AXI4 的读取和写入通道是独立的。
例如,像这样的系统,
CPU <> PCIE 控制器 <->PCIE AXI 桥接器 <-> AXI4,带 DEC 和 DDR 从站(DEC 模块连接到 AXI4 从数据端口 0 和 APB 寄存器端口,DDR 内存模块连接到 AXI4 从数据端口 1(
CPU执行以下两个操作,
1.CPU writes data to DDR
2.CPU writes DEC APB register to start DEC
由于 PCIE 内存写入(预取和不可预取(已发布,即没有响应,PCIE AXI 桥接器将使用相同的 ID 依次执行上述两个操作,但不等待BRESP。在数据到达DDR之前,DEC可能已经看到APB寄存器写入并开始读取数据,因此数据可能较旧且无效。
此排序问题可以通过写入数据然后将其读回来解决,如下所示:
1.CPU writes data to DDR
2.CPU read the same data back
3.CPU writes DEC APB register to start DEC
但它效率低下。
那么,当 PCIE 和 AXI4 连接时,我们如何解决此排序问题呢?在 PCIE 端还是 AXI 互连端解决此排序问题更好?
当我查看 Linux Kennel 代码设备驱动程序时,我看到了同样的问题,先写到这个寄存器,然后写这个寄存器,但我怎么知道第一个已经完成?在很多情况下,驱动程序将简单地读回相同的寄存器或应该显示副作用的寄存器。例如,nvme设备可以通过一个寄存器写入来复位,但在另一个寄存器读取返回特定值之前,您不知道操作已完成。请注意 nvme_enable_ctrl 函数,它写入 32 reg,然后立即停止,直到读取返回特定值。因此,我建议遵循过去开发的决定,而不是包装自己的解决方案。
https://elixir.bootlin.com/linux/latest/source/drivers/nvme/host/core.c#L2169