dma_alloc_coherent从第一个参数device->dma_mem中分配内存
dma_mem一致性内存可以有2种方式提供
1、dts中dma-range指定
。。。
2、dts中memory-region索引的reserved-memory分配
of_reserved_mem_device_init (要求reserved内存shared-dma-pool)
rmem_dma_ops.device_init() = rmem_dma_device_init 将reserved-memory内存一致性建页表(memremap(MEMREMAP_WC))并绑定到dev->dma_mem中。
分配时
dma_alloc_coherent ==> dma_alloc_from_coherent即可从上述映射的一致性内存分配。
过程如下:
1、从系统内存分配物理地址和虚拟地址
dma_alloc_coherent(dev, GFP_KERNEL | GFP_DMA) 可被中断
dma_alloc_coherent(dev, GFP_ATOMIC) = pci_alloc_consistent 从预留的cma_pool分配,不可被中断
上述直接调用方式只能从Iinux管理系统内存中动态分配
2、从mem_region区域分配内存
device_tree:
aaa_pgtable_reserved {
compatible = "shared-dma-pool";
reg = <0x1 0x10000000 0 0x200000>;
no-map;
};
bbb {
compatible = "xxxx"
reg = ...;
interrupts = ...;
interrupt-parent = ...;
memory_region = <&aaa_pgtable_reserved>;
}
driver
...
#include <linux/of_reserved_mem.h>
...
static int xxx_dev_probe(struct device *dev, ...)
{
...
dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
ret = of_reserved_mem_device_init(dev);
...
}
之后即可使用dma_alloc_coherent(dev, GFP_KERNEL)分配
另一种一致性内存分配方式 dma-ranges
// BUS_ADDRESS(3) CPU_PHYSICAL(2) SIZE(2)
dma-ranges = <0x02 0x0 0x0 0x0 0x0 0x40000000>;
初始化:
of_dma_configure ==>
of_dma_get_range
arch_setup_dma_ops ==>
dev->archdata.dma_ops = &swiotlb_dma_ops;
分配一致性内存:
dma_alloc_coherent ==>
dma_alloc_attrs ==>
ops = get_dma_ops() 即swiotlb_dma_ops
cpu_addr = ops->alloc()
__dma_alloc ==>
__dma_alloc_coherent ==>
swiotlb_alloc_coherent ==>
__get_free_pages()