ION原理分析

平台: MSM8x25Q

系统: Android4.1

从上一篇ION基本概念中,我们了解了heaptype, heap id, client, handle以及如何使用,本篇再从原理上分析下ION的运作流程。

         MSM8x25Q平台使用的是board-qrd7627.c,ION相关定义如下:

/**
 * These heaps are listed in the order they will be allocated.
 * Don't swap the order unless you know what you are doing!
 */
struct ion_platform_heap msm7627a_heaps[] = {
		{
			.id	= ION_SYSTEM_HEAP_ID,
			.type	= ION_HEAP_TYPE_SYSTEM,
			.name	= ION_VMALLOC_HEAP_NAME,
		},
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
		/* PMEM_ADSP = CAMERA */
		{
			.id	= ION_CAMERA_HEAP_ID,
			.type	= CAMERA_HEAP_TYPE,
			.name	= ION_CAMERA_HEAP_NAME,
			.memory_type = ION_EBI_TYPE,
			.extra_data = (void *)&co_mm_ion_pdata,
			.priv	= (void *)&ion_cma_device.dev,
		},
		/* AUDIO HEAP 1*/
		{
			.id	= ION_AUDIO_HEAP_ID,
			.type	= ION_HEAP_TYPE_CARVEOUT,
			.name	= ION_AUDIO_HEAP_NAME,
			.memory_type = ION_EBI_TYPE,
			.extra_data = (void *)&co_ion_pdata,
		},
		/* PMEM_MDP = SF */
		{
			.id	= ION_SF_HEAP_ID,
			.type	= ION_HEAP_TYPE_CARVEOUT,
			.name	= ION_SF_HEAP_NAME,
			.memory_type = ION_EBI_TYPE,
			.extra_data = (void *)&co_ion_pdata,
		},
		/* AUDIO HEAP 2*/
		{
			.id    = ION_AUDIO_HEAP_BL_ID,
			.type  = ION_HEAP_TYPE_CARVEOUT,
			.name  = ION_AUDIO_BL_HEAP_NAME,
			.memory_type = ION_EBI_TYPE,
			.extra_data = (void *)&co_ion_pdata,
			.base = BOOTLOADER_BASE_ADDR,
		},

#endif
};

static struct ion_co_heap_pdata co_ion_pdata = {
	.adjacent_mem_id = INVALID_HEAP_ID,
	.align = PAGE_SIZE,
};

static struct ion_co_heap_pdata co_mm_ion_pdata = {
	.adjacent_mem_id = INVALID_HEAP_ID,
	.align = PAGE_SIZE,
};

static u64 msm_dmamask = DMA_BIT_MASK(32);

static struct platform_device ion_cma_device = {
	.name = "ion-cma-device",
	.id = -1,
	.dev = {
		.dma_mask = &msm_dmamask,
		.coherent_dma_mask = DMA_BIT_MASK(32),
	}
};

Qualcomm提示了不要轻易调换顺序,因为后面代码处理是将顺序定死了的,一旦你调换了,代码就无法正常运行了。

另外, 本系统中只使用了ION_HEAP_TYPE_CARVEOUT和 ION_HEAP_TYPE_SYSTEM这两种heap type.

对于ION_HEAP_TYPE_CARVEOUT的内存分配,后面将会发现,其实就是之前讲述过的使用mem pool来分配的。

Platform device如下,在msm_ion.c中用到。

static struct ion_platform_data ion_pdata = {
	.nr = MSM_ION_HEAP_NUM,
	.has_outer_cache = 1,
	.heaps = msm7627a_heaps,
};

static struct platform_device ion_dev = {
	.name = "ion-msm",
	.id = 1,
	.dev = { .platform_data = &ion_pdata },
};

ION初始化

转到msm_ion.c,ion.c的某些函数也被重新封装了下.万事都从设备匹配开始:

static struct platform_driver msm_ion_driver = {
	.probe = msm_ion_probe,
	.remove = msm_ion_remove,
	.driver = { .name = "ion-msm" }
};
static int __init msm_ion_init(void)
{
	/*调用msm_ion_probe */
	return platform_driver_register(&msm_ion_driver);
}

static int msm_ion_probe(struct platform_device *pdev)
{
	/*即board-qrd7627a.c中的ion_pdata */
	struct ion_platform_data *pdata = pdev->dev.platform_data;
	int err;
	int i;

	/*heap数量*/
	num_heaps = pdata->nr;
	/*分配struct ion_heap */
	heaps = kcalloc(pdata->nr, sizeof(struct ion_heap *), GFP_KERNEL);

	if (!heaps) {
		err = -ENOMEM;
		goto out;
	}
	/*创建节点,最终是/dev/ion,供用户空间操作。*/
	idev = ion_device_create(NULL);
	if (IS_ERR_OR_NULL(idev)) {
		err = PTR_ERR(idev);
		goto freeheaps;
	}
	/*最终是根据adjacent_mem_id 是否定义了来分配相邻内存,
我们没用到,忽略此函数。*/
	msm_ion_heap_fixup(pdata->heaps, num_heaps);

	/* create the heaps as specified in the board file */
	for (i = 0; i < num_heaps; i++) {
		struct ion_platform_heap *heap_data = &pdata->heaps[i];
		/*分配ion*/
		msm_ion_allocate(heap_data);

		heap_data->has_outer_cache = pdata->has_outer_cache;
		/*创建ion heap。*/
		heaps[i] = ion_heap_create(heap_data);
		if (IS_ERR_OR_NULL(heaps[i])) {
			heaps[i] = 0;
			continue;
		} else {
			if (heap_data->size)
				pr_info("ION heap %s created at %lx "
					"with size %x\n", heap_data->name,
							  heap_data->base,
							  heap_data->size);
			else
				pr_info("ION heap %s created\n",
							  heap_data->name);
		}
		/*创建的heap添加到idev中,以便后续使用。*/
		ion_device_add_heap(idev, heaps[i]);
	}
	/*检查heap之间是否有重叠部分*/
	check_for_heap_overlap(pdata->heaps, num_heaps);
	platform_set_drvdata(pdev, idev);
	return 0;

freeheaps:
	kfree(heaps);
out:
	return err;
}

通过ion_device_create创建/dev/ion节点:
struct ion_device *ion_device_create(long (*custom_ioctl)
				     (struct ion_client *client,
				      unsigned int cmd,
				      unsigned long arg))
{
	struct ion_device *idev;
	int ret;
	
	idev = kzalloc(sizeof(struct ion_device), GFP_KERNEL);
	if (!idev)
		return ERR_PTR(-ENOMEM);
	/*是个misc设备*/
	idev->dev.minor = MISC_DYNAMIC_MINOR;
	/*节点名字为ion*/
	idev->dev.name = "ion";
	/*fops为ion_fops,所以对应ion的操作都会调用ion_fops的函数指针。*/
	idev->dev.fops = &ion_fops;
	idev->dev.parent = NULL;
	ret = misc_register(&idev->dev);
	if (ret) {
		pr_err("ion: failed to register misc device.\n");
		return ERR_PTR(ret);
	}
	/*创建debugfs目录,路径为/sys/kernel/debug/ion/*/
	idev->debug_root = debugfs_create_dir("ion", NULL);
	if (IS_ERR_OR_NULL(idev->debug_root))
		pr_err("ion: failed to create debug files.\n");

	idev->custom_ioctl = custom_ioctl;
	idev->buffers = RB_ROOT;
	mutex_init(&idev->lock);
	idev->heaps = RB_ROOT;
	idev->clients = RB_ROOT;
	/*在ion目录下创建一个check_leaked_fds文件,用来检查Ion的使用是否有内存泄漏。如果申请了ion之后不需要使用却没有释放,就会导致memory leak.*/
	debugfs_create_file("check_leaked_fds", 0664, idev->debug_root, idev,
			    &debug_leak_fops);
	return idev;
}

msm_ion_allocate&
  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值