Linux内核驱动:ion memory

高通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文件中去掉也是可以的。

ION_SYSTEM_HEAP_ID的分配使用

你可能感兴趣的:(Linux内核驱动:ion memory)