内存分配之CMA

 

一.CMA相关的宏

RESERVEDMEM_OF_DECLARE(cma, "shared-dma-pool", rmem_cma_setup);

 

#define RESERVEDMEM_OF_DECLARE(name, compat, init) \

_OF_DECLARE(reservedmem, name, compat, init, reservedmem_of_init_fn)

///      __reservedmem_of_table    __of_table_cma

#if defined(CONFIG_OF) && !defined(MODULE)

#define _OF_DECLARE(table, name, compat, fn, fn_type) \

static const struct of_device_id __of_table_##name \

    __used __section(__##table##_of_table) \

 = { .compatible = compat, \

     .data = (fn == (fn_type)NULL) ? fn : fn  }

#else

#define _OF_DECLARE(table, name, compat, fn, fn_type) \

static const struct of_device_id __of_table_##name \

    __attribute__((unused)) \

 = { .compatible = compat, \

     .data = (fn == (fn_type)NULL) ? fn : fn }

#endif

1.1一般内存的初始化化

setup_arch--->setup_machine_fdt--->early_init_dt_scan--->early_init_dt_scan_nodes--->early_init_dt_add_memory_arch--->memblock_add

1.2 reserved-memory

init.c arm_memblock_init()

fdt.c   ----early_init_fdt_reserve_self();

         ----early_init_fdt_scan_reserved_mem()

                 __fdt_scan_reserved_mem //  of_reserved_mem.c

                      __reserved_mem_reserve_reg

                            |-----early_init_dt_reserve_memory_arch

                            |-----fdt_reserved_mem_save_node   在这个函数中,reserved-mem节

点下的子节点会解析出来,保存到数组//reserved_mem[reserved_mem_count]中,保存完后,

reserved_mem_count增加。

fdt_init_reserved_mem()  // of_reserved_mem.c,遍历数组reserved_mem

                 |----struct reserved_mem *rmem = &reserved_mem[i];

                  __reserved_mem_alloc_size

                  __reserved_mem_init_node()//在遍历的过程中,每个数组成员比对compatible是否是"shared-dma-pool",

如果是,则执行rmem_cma_setup,初始化该块CMA

        ----dma_contiguous_reserve(arm_dma_limit);//cmdline的配置

1.3 device tree example

一下示例来自于内核文档reserved-memory.txt

/ {

#address-cells = <1>;

#size-cells = <1>;

memory {

reg = <0x40000000 0x40000000>;

};

reserved-memory {

#address-cells = <1>;

#size-cells = <1>;

ranges;

/* global autoconfigured region for contiguous allocations */

linux,cma {

compatible = "shared-dma-pool";

reusable;

size = <0x4000000>;

alignment = <0x2000>;

linux,cma-default;

};

display_reserved: framebuffer@78000000 {

compatible = "shared-dma-pool";

reg = <0x78000000 0x800000>;

};

multimedia_reserved: multimedia@77000000 {

compatible = "acme,multimedia-memory";

reg = <0x77000000 0x4000000>;

};

};

/* ... */

fb0: video@12300000 {

memory-region = <&display_reserved>;

/* ... */

};

scaler: scaler@12500000 {

memory-region = <&multimedia_reserved>;

/* ... */

};

codec: codec@12600000 {

memory-region = <&multimedia_reserved>;

/* ... */

};

};

二.各个具体的设备初始化并且使用固定一块的reserved_mem

static int codec_mm_probe(struct platform_device *pdev)

{

int r;

pdev->dev.platform_data = get_mem_mgt();

r = of_reserved_mem_device_init(&pdev->dev); //根据memory-region来找到某个dma块

if (r == 0)

pr_debug("codec_mm_probe mem init done\n");

}

static inline int of_reserved_mem_device_init(struct device *dev)

{

return of_reserved_mem_device_init_by_idx(dev, dev->of_node, 0);

}

int of_reserved_mem_device_init_by_idx(struct device *dev,  struct device_node *np, int idx)

{

target = of_parse_phandle(np, "memory-region", idx);

}

三.通过 bootarg来配置CMA

Cmdline指定:

在bootargs可以添加cma属性指定cma区域,如下所示:

  Bootargs=”cma=0x40000@0x70000000-0x80000000”

其中0x400000是大小,0x70000000-0x80000000指定cma的分配区间。

a) drivers/base/dma-contiguous.c文件中,

early_param("cma", early_cma) 解析bootargs的cmd参数,并将cma的大小赋值给size_cmdline,cma的起始地址赋值给base_cmdline,cma的结束地址赋值给limit_cmdline。

b) arch/arm/kernel/setup.c 文件中,

setup_arch

arm_memblock_init

dma_contiguous_reserve

在dma_contiguos_reserve过程中会将size,base和limit对齐4M,dma_contiguous_default_area。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值