1

我想为在我控制之外分配的内存缓冲区设置 DMA 映射。dma_map_single 似乎是要使用的正确 API,但我的硬件有一个限制,因此映射不能跨越某些二次幂边界,例如 1K。被映射的缓冲区的大小总是小于边界值,但在其他方面是可变的。所以看起来 DMA 池可能无法工作,因为它们需要固定大小,即使“分配”部分是我需要的。

我是否应该继续做 dma_map_single 并检查映射是否满足我的要求,如果不满足则释放映射?这会导致可能返回相同的映射,从而导致永无止境的搜索吗?如果是这样,我可以保留不合适的映射,直到找到合适的映射,然后一次性释放所有不合适的映射。然而,这些听起来并不是好主意。

有没有人有其他/更好的想法?

谢谢。

4

1 回答 1

2

如果您不能保证传递的缓冲区符合您的标准,您可能需要在 DMA 之前分配一个辅助缓冲区并复制到该缓冲区/从该缓冲区复制。在没有 IOMMU 或其他地址转换硬件的平台(例如经典 x86、ARM 等)上,DMA 映射操作实际上只是转换为物理地址。因此,如果您取消映射并使用相同的缓冲区重试,您将始终返回相同的 DMA 地址。

在大多数(所有?)其他确实有 IOMMU 的平台上,翻译仍然在块 >= PAGE_SIZE 上完成。换句话说,如果你在一个有 4K 页面的平台上,并且你在 0xABCDExxx 的缓冲区上进行 DMA 映射,你总是会得到一个像 0xFGHIJxxx 这样的 DMA 地址,其中地址“xxx”的低部分保持不变。(这是因为 IOMMU 像普通的 MMU 一样工作,只查找页面翻译,只保留低 12 位或其他任何位)

因此,基本上在所有平台上的所有情况下,您都不能使用 DMA API 来修复您传递的缓冲区的对齐方式。正如我所说,如果您传入的缓冲区不符合您的对齐要求,我认为唯一的选择是使用反弹缓冲区。DMA 池 API 是分配这些反弹缓冲区的好方法——如果您有时需要较小的缓冲区,这没问题;可以保留一些未使用的内存。

于 2012-09-07T22:35:05.517 回答