【发布时间】:2021-12-12 19:16:42
【问题描述】:
Streaming DMA API 的文档中提到,为了保证一致性,缓存需要在 dma-mapping 到设备之前刷新,在从设备取消映射后失效。
但是,我很困惑是否需要显式执行刷新和失效,即,dma_map_single() 和 dma_sync_single_for_device() 函数是否已经负责刷新缓存线,或者驱动程序开发是否需要调用某些函数来显式刷新 dma 缓冲区的缓存线? dma_unmap_single() 和 dma_sync_single_for_cpu() 也是如此。这两个函数会自动使 dma-buffer 缓存行失效吗?
我浏览了一些使用流式 dma 的现有驱动程序,但看不到任何显式调用来刷新或使缓存线无效。
我还查看了内核源代码,似乎上述函数在其架构特定的实现中都“使缓存行无效”,这进一步增加了我的困惑..例如,在 arch/arm64/mm /cache.S
SYM_FUNC_START_PI(__dma_map_area)
add x1, x0, x1
cmp w2, #DMA_FROM_DEVICE
b.eq __dma_inv_area
b __dma_clean_area
SYM_FUNC_END_PI(__dma_map_area)
有人可以澄清一下吗?谢谢。
【问题讨论】:
-
映射函数将刷新 CPU 端的缓存。如果您在两者之间更新缓冲区,则需要将其同步到设备,或者如果设备有新数据到来,则需要将其同步到 CPU。您可以通过使用 DMA 相干区域来避免所有这些。
-
所以..我不需要调用 dma_cache_inv() 或 dma_cache_wb() 之类的函数来确保一致性..只需 map()/unmap() 或同步操作。感谢您的澄清。我被限制使用 DMA 流来尝试提高性能。
-
当您映射该区域时,无需刷新缓存,当您重新使用该内存时,您必须确保数据是实际,这是通过 DMA 同步 API 调用完成的。如果需要,它们会刷新缓存,但在某些平台上,您可能需要额外的工作。这完全取决于架构。
标签: caching linux-kernel linux-device-driver dma