参考资料:
ldd3第15章:内存映射和DMA
linux source/Documentation/DMA-API.txt
linux source/Documentation/DMA-API-HOWTO.txt
=============================================================
对DMA内存的使用有两种方式:
1,一致DMA映射
通过dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag)来直接得到一块用于dma的内存,同时得到这一段内存的虚拟地址和总线地址,分别用于CPU和device的访问。
通过这种方式得到的dma内存,开发者不用担心cache的问题,但是要注意在执行DMA操作之前flush write buffer。
2,流式DMA映射
先通过kmalloc, get_free_pages等得到一段物理连续的内存空间(注意,除非目标平台有IOMMU,否则必须要求物理地址连续,即vmalloc分配得到的内存空间不能用于DMA操作。)
然后使用dma_map_single, dma_map_pages, dma_map_sg将之前分配的内存空间映射,得到总线地址,使之能被device访问。
这种方式不保证cache的一致性,需要开发者手动处理(调用dma_sync_single_for_cpu/device函数?);
另外,必须保证内存的虚拟地址空间边界与cache line length对齐,因cache line length不确定,所以一般选择page 对齐。
一致DMA映射具有更长的生命周期,它在driver的整个生命周期内都有效,且不用关心cache效应。
流式DMA映射则只在driver填充完要传输的内容到device完成传输这段时间内有效(理论上是从map到unmap,但有效时间如前所述),凡使用流式DMA映射的内存区域在map之后,就只对device有效,driver在unmap之前不能在读写这一段内存区域。或者使用dma_sync_single_for_cpu由cpu获得读写权利,然后driver可对其进行读写。
待续。。。
阅读(1701) | 评论(0) | 转发(0) |