2012年(82)
分类: LINUX
2012-07-03 15:37:11
1. 为什么存在DMA ZONE?
原因是某些硬件的DMA引擎不能访问到所有的内存区域,因此,加上一个DMA ZONE,当使用GFP_DMA方式申请内存时,获得的内存限制在DMA_ZONE的范围内,这些特定的硬件需要使用GFP_DMA方式获得可以做DMA的内存;
如果系统中所有的设备都可选址所有的内存,那么DMA ZONE覆盖所有内存。
2. device结构体的dma_mask和dma_coherent_mask的作用分别是什么?
dma_mask是设备DMA能访问的内存范围,dma_coherent_mask则作用于申请一致性DMA缓冲区。
3. dma_alloc_coherent分配的内存一定在DMA ZONE内吗?
答案是否定的,应该说绝对多数情况下都不在DMA ZONE内。dma_alloc_coherent会调用__dma_alloc,__dma_alloc判断是否从DMA ZONE申请内存的依据是:
u64 mask = get_coherent_dma_mask(dev);
…
if (mask < 0xffffffffULL)
gfp |= GFP_DMA;
page = alloc_pages(gfp, order);
if (!page)
goto no_page;
由此可见,只有当设备的dma_coherent_mask小于全部地址访问 (0xFFFFFFFF)的时候,也就是针对少数特殊设备,才会去DMA ZONE申请内存,其他时候直接从NORMAL ZONE获得内存。而对于绝大多数设备而言,DMA寻址范围是0xFFFFFFFF。
4. 什么时候需要DMA bounce?
最常见的case是,当底层驱动做DMA操作时所使用的内存不是透过 dma_alloc_coherent等一致性DMA缓冲区API获得,而是来自于驱动的上层,譬如文件系统,那么驱动在执行DMA操作时,会调用流式 DMA API,如map_single等。而如果上层传下来的内存超过了设备DMA可寻址的内存范围,即:
needs_bounce = (dma_addr | (dma_addr + size - 1)) & ~mask;
得到满足的时候,这片区域不能执行DMA,map_single底层会自动执行DMA。