DMA 属性¶
本文档描述了 linux/dma-mapping.h 中定义的 DMA 属性的语义。
DMA_ATTR_WEAK_ORDERING¶
DMA_ATTR_WEAK_ORDERING 指定对映射的读写可以是弱有序的,即读写操作可能相互超越。
由于平台实现 DMA_ATTR_WEAK_ORDERING 是可选的,因此未实现的平台将简单地忽略该属性并表现出默认行为。
DMA_ATTR_WRITE_COMBINE¶
DMA_ATTR_WRITE_COMBINE 指定对映射的写入可以被缓冲以提高性能。
由于平台实现 DMA_ATTR_WRITE_COMBINE 是可选的,因此未实现的平台将简单地忽略该属性并表现出默认行为。
DMA_ATTR_NO_KERNEL_MAPPING¶
DMA_ATTR_NO_KERNEL_MAPPING 允许平台避免为已分配的缓冲区创建内核虚拟映射。在某些架构上,创建此类映射并非易事,并且会消耗非常有限的资源(例如内核虚拟地址空间或 DMA 一致性地址空间)。使用此属性分配的缓冲区只能通过调用 dma_mmap_attrs()
传递给用户空间。通过使用此 API,你保证不会解引用 dma_alloc_attr() 返回的指针。你可以将其视为一个必须传递给 dma_mmap_attrs()
和 dma_free_attrs() 的“cookie”。确保这两个函数在每次调用时也设置此属性。
由于平台实现 DMA_ATTR_NO_KERNEL_MAPPING 是可选的,因此未实现的平台将简单地忽略该属性并表现出默认行为。
DMA_ATTR_SKIP_CPU_SYNC¶
默认情况下,dma_map_{single,page,sg} 函数族将给定的缓冲区从 CPU 域传输到设备域。一些高级用例可能需要在一个以上的设备之间共享缓冲区。这需要为每个设备单独创建映射,并且通常通过对给定缓冲区多次调用 dma_map_{single,page,sg} 函数来完成,其中设备指针指向参与缓冲区共享的每个设备。第一次调用将缓冲区从“CPU”域传输到“设备”域,这会同步给定区域的 CPU 缓存(通常这意味着根据 DMA 方向,缓存已被刷新或失效)。然而,对其他设备后续调用 dma_map_{single,page,sg}() 将在 CPU 缓存上执行完全相同的同步操作。CPU 缓存同步可能是一个耗时的操作,特别是如果缓冲区很大,因此如果可能,强烈建议避免它。DMA_ATTR_SKIP_CPU_SYNC 允许平台代码跳过给定缓冲区的 CPU 缓存同步,前提是该缓冲区已传输到“设备”域。此属性也可以用于 dma_unmap_{single,page,sg} 函数族,以强制缓冲区在释放其映射后保留在设备域中。请谨慎使用此属性!
DMA_ATTR_FORCE_CONTIGUOUS¶
默认情况下,DMA 映射子系统允许将 dma_alloc_attrs() 函数分配的缓冲区从单个页面组装起来,前提是它可以作为连续块映射到设备 DMA 地址空间中。通过指定此属性,分配的缓冲区也被强制在物理内存中是连续的。
DMA_ATTR_ALLOC_SINGLE_PAGES¶
这是对 DMA 映射子系统的一个提示,表明可能不值得花时间以提供更好 TLB 效率的方式分配内存(即不值得尝试使用更大的页面来构建映射)。你可能希望在以下情况下指定此属性:
你知道对这块内存的访问不会导致 TLB 颠簸。你可能知道访问很可能是顺序的,或者它们不是顺序的,但不太可能在许多可能位于不同物理页面的地址之间来回切换。
你知道访问内存时 TLB 未命中的开销足够小,可以忽略不计。如果你正在执行解密或解压缩等繁重操作,则可能属于这种情况。
你知道 DMA 映射是相当短暂的。如果你预期映射的生命周期很短,那么优化分配(避免使用大页面)可能比获得大页面带来的微小性能提升更值得。
设置此提示并不能保证你不会获得巨页,但它意味着我们不会那么努力地去获取它们。
注意
目前 DMA_ATTR_ALLOC_SINGLE_PAGES 仅在 ARM 上实现,不过 ARM64 的补丁可能很快就会发布。
DMA_ATTR_NO_WARN¶
这会告诉 DMA 映射子系统抑制分配失败报告(类似于 __GFP_NOWARN)。
在某些架构上,分配失败会通过错误消息报告到系统日志。虽然这有助于识别和调试问题,但那些处理失败(例如稍后重试)的驱动程序并没有问题,并且实际上可能会用根本不是问题的错误消息淹没系统日志,具体取决于重试机制的实现。
因此,这为驱动程序提供了一种方法,可以在分配失败不是问题且不应干扰日志的调用中避免这些错误消息。
注意
目前 DMA_ATTR_NO_WARN 仅在 PowerPC 上实现。
DMA_ATTR_PRIVILEGED¶
一些高级外设,例如远程处理器和 GPU,在特权“supervisor”模式和非特权“user”模式下都执行对 DMA 缓冲区的访问。此属性用于向 DMA 映射子系统指示缓冲区在较高特权级别完全可访问(理想情况下,在较低特权级别不可访问或至少只读)。