对于函数dma_map_single()和函数dma_map_page(),它们的操作类似,对一块物理内存进行映射,且最终会调用dma_map_page_attrs()。它们的差别为,dma_map_single()将一块物理连续内存进行映射,而dma_map_page()将一页物理内存进行映射。
与之前dma_map_sg()类似,同样分为直接映射和使能SMMU情况。

1 DMA直接映射情况
与dma_map_sg()类似,dma_map_page_attrs()操作如下:

操作过程如下:
- 当使用SWIOTLB时,调用swiotlb_map()进行映射;否则执行操作(2);
- 进行直接映射,调用函数phys_to_dma()让iova=pa;
- 若设备不支持coherent且没有标记DMA_ATTR_SKIP_CPU_SYNC时,软件进行设备的SYNC;
2 SMMU使能情况
对于使能SMMU情况,需要进行DMA映射,如下图所示:

操作过程如下:
- 对于使用swiotlb情况且物理页没有对齐时,使用bounce_page,并进行初始化;
- 当设备不支持coherent且没有标记DMA_ATTR_SKIP_CPU_SYNC时,软件进行设备的SYNC;
- 调用__iommu_dma_map()进行DMA MAP映射。
3 DMA MAP API总结
这里介绍三个DMA MAP函数:dma_alloc_coherent() / dma_map_sg() / dma_map_single() / dma_map_page()。它们的差异如下:
(1)函数dma_alloc_coherent()为静态DMA,其他三个函数为动态DMA,dma_alloc_coherent()除了进行映射外,该函数还需要分配物理内存,其他三个函数则在函数被调用前已经分配好物理内存。因此通常在数据动态传输时通常使用dma_map_*函数,而dma_alloc_coherent()通常用于系统中长期使用的DMA。
(2)对于dma_map_*这三个函数,区别主要表现在物理内存组织方式上:dma_map_sg()将多个连续物理内存进行映射;dma_map_single()将一块连续的物理内存进行映射;dma_map_page()将一个物理页进行映射;

从前面讲述的DMA MAP API可以看出,DMA MAP基本过程为:分配物理内存,分配连续的IOVA,对物理内存和IOVA进行映射。其中分配物理内存后续可以在内存管理模块做讲解,IOVA的分配在前面的章节已经介绍,对于物理内存和IOVA的映射将在后续的页表的操作进行介绍。
本文详细介绍了DMA映射中的dma_map_single()和dma_map_page()函数,它们用于对物理内存进行映射,以供设备使用。dma_map_single()映射单一连续内存块,而dma_map_page()映射一页物理内存。在直接映射和SMMU使能的情况下,两者操作略有不同,涉及物理内存到IOVA的映射以及同步操作。DMA映射过程包括分配物理内存、IOVA和映射,这些将在后续内容中进一步探讨。
函数dma_map_single和dma_map_page&spm=1001.2101.3001.5002&articleId=122849093&d=1&t=3&u=7090fe74cc77471b8cd4473bb06e07ec)
6028

被折叠的 条评论
为什么被折叠?



