下面对几种常见的使用方法进行举例说明:
通过 memremap/ioremap 来使用
在 Device Tree 配置如下,然后通过“memory-region”参数可将该预留内存分配给特定的设备驱动使用:
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
foobar_reserved: foobar@70000000 {
no-map;
reg = <0x0 0x70000000 0x0 0x10000000>;
};
};
foobar_driver: foobar_driver@0 {
memory-region = <&foobar_reserved>;
};
在设备驱动程序中,可解析 Device Tree 节点获得预留内存的物理地址和大小,然后通过 memremap/ioremap 映射这片内存空间来使用:
/* Get reserved memory region from Device-tree */
np = of_parse_phandle(dev->of_node, "memory-region", 0);
if (!np) {
dev_err(dev, "No %s specifiedn", "memory-region");
goto error1;
}
rc = of_address_to_resource(np, 0, &r);
if (rc) {
dev_err(dev, "No memory address assigned to the regionn");
goto error1;
}
lp->paddr = r.start;
lp->vaddr = memremap(r.start, resource_size(&r), MEMREMAP_WB);
dev_info(dev, "Allocated reserved memory, vaddr: 0x%0llX, paddr: 0x%0llXn", (u64)lp->vaddr, lp->paddr);
通过 DMA API 来使用
设置“shared-dma-pool”属性后,可让设备驱动通过 DMA API 来使用预留内存:
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
foobar_reserved: foobar@70000000 {
compatible = "shared-dma-pool";
no-map;
reg = <0x0 0x70000000 0x0 0x10000000>;
};
};
foobar_driver: foobar_driver@0 {
memory-region = <&foobar_reserved>;
};
设备驱动程序中可类似常规地使用 DMA API,它申请的内存不是来源于默认的 CMA 内存池,而是来源于该预留内存:
/* Initialize reserved memory resources */
rc = of_reserved_mem_device_init(dev);
if(rc) {
dev_err(dev, "Could not get reserved memoryn");
goto error1;
}
/* Allocate memory */
dma_set_coherent_mask(dev, 0xFFFFFFFF);
lp->vaddr = dma_alloc_coherent(dev, ALLOC_SIZE, &lp->paddr, GFP_KERNEL);
dev_info(dev, "Allocated coherent memory, vaddr: 0x%0llX, paddr: 0x%0llXn", (u64)lp->vaddr, lp->paddr);
给 CMA 预留内存
有时我们不需要将预留内存分配给特定的设备驱动,而只是想给默认 CMA 内存池分配一片固定的内存区域,这时我们可配置上“reusable”和“linux,cma-default”:
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
linux,cma {
compatible = "shared-dma-pool";
reusable;
reg = <0x0 0x70000000 0x0 0x10000000>;
linux,cma-default;
};
};
由此可见,不同于 memreserve,通过 reserved-memory 预留的内存有可能进入系统 CMA,这需要满足以下几个条件:
- compatible 需要为“shared-dma-pool”
- 没有定义“no-map”属性
- 定义了“reusable”属性
下面对几种常见的使用方法进行举例说明:
通过 memremap/ioremap 来使用
在 Device Tree 配置如下,然后通过“memory-region”参数可将该预留内存分配给特定的设备驱动使用:
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
foobar_reserved: foobar@70000000 {
no-map;
reg = <0x0 0x70000000 0x0 0x10000000>;
};
};
foobar_driver: foobar_driver@0 {
memory-region = <&foobar_reserved>;
};
在设备驱动程序中,可解析 Device Tree 节点获得预留内存的物理地址和大小,然后通过 memremap/ioremap 映射这片内存空间来使用:
/* Get reserved memory region from Device-tree */
np = of_parse_phandle(dev->of_node, "memory-region", 0);
if (!np) {
dev_err(dev, "No %s specifiedn", "memory-region");
goto error1;
}
rc = of_address_to_resource(np, 0, &r);
if (rc) {
dev_err(dev, "No memory address assigned to the regionn");
goto error1;
}
lp->paddr = r.start;
lp->vaddr = memremap(r.start, resource_size(&r), MEMREMAP_WB);
dev_info(dev, "Allocated reserved memory, vaddr: 0x%0llX, paddr: 0x%0llXn", (u64)lp->vaddr, lp->paddr);
通过 DMA API 来使用
设置“shared-dma-pool”属性后,可让设备驱动通过 DMA API 来使用预留内存:
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
foobar_reserved: foobar@70000000 {
compatible = "shared-dma-pool";
no-map;
reg = <0x0 0x70000000 0x0 0x10000000>;
};
};
foobar_driver: foobar_driver@0 {
memory-region = <&foobar_reserved>;
};
设备驱动程序中可类似常规地使用 DMA API,它申请的内存不是来源于默认的 CMA 内存池,而是来源于该预留内存:
/* Initialize reserved memory resources */
rc = of_reserved_mem_device_init(dev);
if(rc) {
dev_err(dev, "Could not get reserved memoryn");
goto error1;
}
/* Allocate memory */
dma_set_coherent_mask(dev, 0xFFFFFFFF);
lp->vaddr = dma_alloc_coherent(dev, ALLOC_SIZE, &lp->paddr, GFP_KERNEL);
dev_info(dev, "Allocated coherent memory, vaddr: 0x%0llX, paddr: 0x%0llXn", (u64)lp->vaddr, lp->paddr);
给 CMA 预留内存
有时我们不需要将预留内存分配给特定的设备驱动,而只是想给默认 CMA 内存池分配一片固定的内存区域,这时我们可配置上“reusable”和“linux,cma-default”:
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
linux,cma {
compatible = "shared-dma-pool";
reusable;
reg = <0x0 0x70000000 0x0 0x10000000>;
linux,cma-default;
};
};
由此可见,不同于 memreserve,通过 reserved-memory 预留的内存有可能进入系统 CMA,这需要满足以下几个条件:
- compatible 需要为“shared-dma-pool”
- 没有定义“no-map”属性
- 定义了“reusable”属性
举报