Linux 流式传输 DMA 重新映射而不取消映射

Linux Streaming DMA ReMapping without Unmapping

我注意到pci_unmap_sg(我展示的是dma_unmap_sg_attrs,由pci_unmap_sg通过两个宏调用,参数命名清晰)的签名包括方向和属性。

static inline void dma_unmap_sg_attrs(
   struct device *dev,
   struct scatterlist *sg, 
   int nents,
   enum dma_data_direction dir, 
   struct dma_attrs *attrs)

我想知道为什么需要知道解映射的方向和属性。最初我认为映射有点像 mallocfree。但是看到这个我想知道像下面这样的东西是否合法:

dma_map_sg_attrs(..., dir=DMA_BIDIRECTIONAL,...);
...
dma_unmap_sg_attrs(..., dir=DMA_FROM_DEVICE ,...);
//continue use in TO_DEVICE direction

dma_map_sg_attrs(..., dir=DMA_TO_DEVICE,...);
...
dma_map_sg_attrs(..., dir=DMA_FROM_DEVICE ,...);
//start bidirectional use

我也可以这样做吗(通过 DMA 将数据从一个设备流式传输到另一个设备,如果它们不能直接相互 dma):

dma_map_sg_attrs(dev1, ..., dir=DMA_FROM_DEVICE ,...);
dma_map_sg_attrs(dev2, ..., dir=DMA_TO_DEVICE ,...);

我尝试深入研究函数,但在 get_dma_ops 处结束,它从全局获取函数指针。但是如何进一步遵循这段代码是另一个


更新

我发现同步 api 更令人困惑:

pci_dma_sync_sg_for_cpu(
  struct pci_dev *hwdev,
  struct scatterlist *sg,
  int nelems,
  int direction
)

这个api知道方向的原因是什么?是不是api就没有办法记住原来的映射方向,如果只映射成DMA_TO_DEVICE,是不是就把sync_for_cpu去掉了?

答案既简单又可靠。这取决于您对所使用的 CPU 架构的了解程度。 DMA 的问题是 CPU 缓存。 CPU 缓存必须与 DMA 一致。因此,我们在同步 API 中有不同的方向,因为我们可能 从 DMA 和 CPU 双方访问 数据。正如您已经知道的那样,同步 API 是地图 API.

中方向参数的原因

P.S。无论如何,这不是全面的答案。为此,您必须阅读特定的文献和文档。我建议您从 Documentation/DMA*.txt 个文件开始。

Andy 的提示是正确的,虽然我认为大多数 DMA_ATTR_* 不会帮助我,因为我的设备进行排序,所以内核无法处理其中的一些,但是如果你看看 DMA_ATTR_SKIP_SYNC_CPU 你发现(来自 DMA-attributes.txt):

 71 DMA_ATTR_SKIP_CPU_SYNC
 72 ----------------------
 73 
 74 By default dma_map_{single,page,sg} functions family transfer a given
 75 buffer from CPU domain to device domain. Some advanced use cases might
 76 require sharing a buffer between more than one device. This requires
 77 having a mapping created separately for each device and is usually
 78 performed by calling dma_map_{single,page,sg} function more than once
 79 for the given buffer with device pointer to each device taking part in
 80 the buffer sharing. The first call transfers a buffer from 'CPU' domain
 81 to 'device' domain, what synchronizes CPU caches for the given region
 82 (usually it means that the cache has been flushed or invalidated
 83 depending on the dma direction). However, next calls to
 84 dma_map_{single,page,sg}() for other devices will perform exactly the
 85 same synchronization operation on the CPU cache. CPU cache synchronization
 86 might be a time consuming operation, especially if the buffers are
 87 large, so it is highly recommended to avoid it if possible.
 88 DMA_ATTR_SKIP_CPU_SYNC allows platform code to skip synchronization of
 89 the CPU cache for the given buffer assuming that it has been already
 90 transferred to 'device' domain. This attribute can be also used for
 91 dma_unmap_{single,page,sg} functions family to force buffer to stay in
 92 device domain after releasing a mapping for it. Use this attribute with
 93 care!