高通msm平台为例,以下是这个平台定义的几个ion内存。
qcom,ion {
compatible = "qcom,msm-ion";
#address-cells = <1>;
#size-cells = <0>;
qcom,ion-heap@25 {
reg = <25>;
qcom,ion-heap-type = "SYSTEM";
};
qcom,ion-heap@21 {
reg = <21>;
qcom,ion-heap-type = "SYSTEM_CONTIG";
};
qcom,ion-heap@8 { /* CP_MM HEAP */
compatible = "qcom,msm-ion-reserve";
reg = <8>;
qcom,heap-align = <0x1000>;
linux,contiguous-region = <&secure_mem>; //ION_CP_MM_HEAP_ID//msm_semem.c中分配
qcom,ion-heap-type = "SECURE_DMA";
};
qcom,ion-heap@27 { /* QSEECOM HEAP */
compatible = "qcom,msm-ion-reserve";
reg = <27>;
linux,contiguous-region = <&qseecom_mem>;//ION_QSECOM_HEAP_ID//ta_log.c和Qseecom.c
qcom,ion-heap-type = "DMA";
};
qcom,ion-heap@28 { /* AUDIO HEAP */
compatible = "qcom,msm-ion-reserve";
reg = <28>;
linux,contiguous-region = <&audio_mem>;
qcom,ion-heap-type = "DMA";
};
qcom,ion-heap@23 { /* OTHER PIL HEAP */
compatible = "qcom,msm-ion-reserve";
reg = <23>;
linux,contiguous-region = <&peripheral_mem>;
qcom,ion-heap-type = "DMA";
};
qcom,ion-heap@26 { /* MODEM HEAP */
compatible = "qcom,msm-ion-reserve";
reg = <26>;
linux,contiguous-region = <&modem_adsp_mem>;
qcom,ion-heap-type = "DMA";
};
}
这些内容从msm_ion.c 里读出来并根据这些内容创建 ion_platform_heap 数据结构。
struct ion_platform_heap {
enum ion_heap_type type;
unsigned int id;
const char *name;
ion_phys_addr_t base;
size_t size;
unsigned int has_outer_cache;
void *extra_data;
ion_phys_addr_t align;
void *priv;
};
从device tree读出来相应的id,name,base,size等内容然后保存在ion_platform_heap中。
打印的内容如下:
idx=0, type=0,id=25,name=system,base=0x0,size=0
idx=1, type=1,id=21,name=kmalloc,base=0x0,size=0
idx=2, type=6,id=8,name=mm,base=0xb9000000,size=114294784
idx=3, type=4,id=27,name=qsecom,base=0xb8000000,size=13631488
idx=4, type=4,id=28,name=audio,base=0xb7c00000,size=3227648
idx=5, type=4,id=23,name=pil_1,base=0x8c000000,size=6291456
idx=6, type=4,id=26,name=pil_2,base=0x86800000,size=92274688
ion_platform_heap.id : 等于device tree中reg的值。
ion_platform_heap.type : 读出来qcom,ion-heap-type的内容,加上ION_HEAP_TYPE_ 前缀的。
比如qcom,ion-heap-type=”SYSTEM”,然后加上ION_HEAP_TYPE_,这些定义在ion_heap_type枚举类型中。
enum ion_heap_type {
ION_HEAP_TYPE_SYSTEM, //qcom,ion-heap-type = "SYSTEM"
ION_HEAP_TYPE_SYSTEM_CONTIG, //qcom,ion-heap-type="SYSTEM_CONFIG"
ION_HEAP_TYPE_CARVEOUT,
ION_HEAP_TYPE_CHUNK,
ION_HEAP_TYPE_DMA,
ION_HEAP_TYPE_CUSTOM, /* must be last so device specific heaps always
are at the end of this enum */
ION_NUM_HEAPS = 16,
};
ion_platform_heap.name : 根据ion_platform_heap.id值和ion_heap_meta.id进行比较,把对应的 ion_heap_meta.name赋值给 ion_platform_heap.name。ion_heap_meta 定义如下。
static struct ion_heap_desc ion_heap_meta[] = {
{
.id = ION_SYSTEM_HEAP_ID,
.name = ION_SYSTEM_HEAP_NAME,
},
{
.id = ION_SYSTEM_CONTIG_HEAP_ID,
.name = ION_KMALLOC_HEAP_NAME,
},
{
.id = ION_CP_MM_HEAP_ID,
.name = ION_MM_HEAP_NAME,
.permission_type = IPT_TYPE_MM_CARVEOUT,
},
{
.id = ION_MM_FIRMWARE_HEAP_ID,
.name = ION_MM_FIRMWARE_HEAP_NAME,
},
{
.id = ION_CP_MFC_HEAP_ID,
.name = ION_MFC_HEAP_NAME,
.permission_type = IPT_TYPE_MFC_SHAREDMEM,
},
{
.id = ION_SF_HEAP_ID,
.name = ION_SF_HEAP_NAME,
},
{
.id = ION_QSECOM_HEAP_ID,
.name = ION_QSECOM_HEAP_NAME,
},
{
.id = ION_AUDIO_HEAP_ID,
.name = ION_AUDIO_HEAP_NAME,
},
{
.id = ION_PIL1_HEAP_ID,
.name = ION_PIL1_HEAP_NAME,
},
{
.id = ION_PIL2_HEAP_ID,
.name = ION_PIL2_HEAP_NAME,
},
{
.id = ION_CP_WB_HEAP_ID,
.name = ION_WB_HEAP_NAME,
},
{
.id = ION_CAMERA_HEAP_ID,
.name = ION_CAMERA_HEAP_NAME,
},
{
.id = ION_ADSP_HEAP_ID,
.name = ION_ADSP_HEAP_NAME,
}
};
然后根据每个ion_platform_heap,通过msm_ion_heap_create()函数来创建一个ion_heap。
每个ion_heap通过plist_add(&heap->node, &dev->heaps),把每个创建的ion_heap->node链接到
ion_device->heaps。
msm_ion_heap_create()函数中,根据每种ion_heap_type来初始化每个ion_heap。
ion_heap中ion_heap_ops是根据上面的DMA,或者SYSTEM等来初始化的。
这些创建完了之后,就可以通过ion_alloc()等函数分配使用ion内存。
比如Secure CMA,也就是secure_mem对应的内存,一般是video playback的时候使用的。
在代码中搜索,ION_CP_MM_HEAP_ID 就可以搜出来。
//比如kgsl_drm.c文件中
priv->ion_handle = ion_alloc(kgsl_drm_ion_client,
obj->size * priv->bufcount, PAGE_SIZE,
ION_HEAP(ION_CP_MM_HEAP_ID), ION_FLAG_SECURE);
//比如msm_smem.c文件中
heap_mask = ION_HEAP(ION_CP_MM_HEAP_ID);
ion_alloc(client->clnt, size, align, heap_mask, flags);
ION_SYSTEM_HEAP_ID 这种在 mdss_fb.c 中,或者再 msm_audio_ion.c 中都有使用。
这里可以看到ion系统没有真正使用两个qcom,ion-heap-type 为 “DMA”的部分,这两个部分分别是reg值为23和28的两个部分。(ION_PIL1_HEAP_ID,ION_PIL2_HEAP_ID)。这两个部分是没有通过ion_alloc函数获取相关的内存的。而是在
相应的device tree当中加上linux,contiguous-region,用这个来在platform设备注册的时候把相应的cma区域放到dev->cma_area中,然后在初始化的时候取出来使,看如下:
//有定义linux,contiguous-region,就会在注册platform设备的时候,通过linux,contiguous-region
//把相应的CMA区域放到dev->cma_area中了(具体看CMA说明)。然后在modem上电,分配内存的时候直接取出来
//dev->cma_area使用
qcom,pronto@a21b000 {
compatible = "qcom,pil-tz-generic";
...
linux,contiguous-region = <&peripheral_mem>;
}
qcom,mss@4080000 {
compatible = "qcom,pil-q6v56-mss";
...
linux,contiguous-region = <&modem_adsp_mem>;
}
由于这两个部分是CMA分配使用的,其实可以从msm8916-ion.dtsi文件中去掉也是可以的。