@laocai 找到了libuapi\src\ion_alloc.c中的代码
/* return virtual address: 0 failed */
void* sunxi_ion_alloc_palloc(int size)
{
aw_ion_allocation_info_t alloc_data;
ion_fd_data_t fd_data;
struct ion_handle_data handle_data;
struct aw_ion_custom_info custom_data;
sunxi_phys_data phys_data;
struct user_iommu_param iommu_param;
int rest_size = 0;
unsigned long addr_phy = 0;
unsigned long addr_vir = 0;
buffer_node * alloc_buffer = NULL;
int ret = 0;
char *cache_flag;
pthread_mutex_lock(&g_ion_mutex_alloc);
if (g_ion_alloc_context == NULL) {
loge("call ion_alloc_open\n");
goto ALLOC_OUT;
}
if (size <= 0) {
loge("can not alloc size 0\n");
goto ALLOC_OUT;
}
memset(&alloc_data, 0, sizeof(alloc_data));
memset(&fd_data, 0, sizeof(fd_data));
alloc_data.aw_len = (size_t)size;
alloc_data.aw_align = ION_ALLOC_ALIGN ;
#if defined(CONF_KERNEL_IOMMU)
alloc_data.aw_heap_id_mask = AW_ION_SYSTEM_HEAP_MASK | AW_ION_CARVEOUT_HEAP_MASK;
#else
alloc_data.aw_heap_id_mask = AW_ION_DMA_HEAP_MASK | AW_ION_CARVEOUT_HEAP_MASK;
#endif
cache_flag = getenv("MG_IONBUFFER");
if(cache_flag == NULL || strcmp(cache_flag, "1") != 0){
alloc_data.flags = AW_ION_CACHED_FLAG | AW_ION_CACHED_NEEDS_SYNC_FLAG;
}
#if CONF_KERNEL_VERSION_OLD
ret = ioctl(g_ion_alloc_context->fd, AW_MEM_ION_IOC_ALLOC, &alloc_data);
if (ret) {
loge("ION_IOC_ALLOC error\n");
goto ALLOC_OUT;
}
/* get dmabuf fd */
fd_data.handle = alloc_data.handle;
ret = ioctl(g_ion_alloc_context->fd, AW_MEM_ION_IOC_MAP, &fd_data);
if (ret) {
loge("ION_IOC_MAP err, ret %d, dmabuf fd 0x%08x\n",
ret, (unsigned int)fd_data.aw_fd);
goto ALLOC_OUT;
}
#else
struct aw_ion_new_alloc_data data = {
.len = alloc_data.aw_len,
.heap_id_mask = alloc_data.aw_heap_id_mask,
.flags = alloc_data.flags,
};
ret = ioctl(g_ion_alloc_context->fd, AW_ION_IOC_NEW_ALLOC, &data);
if (ret < 0) {
loge("AW_ION_IOC_NEW_ALLOC error\n");
goto ALLOC_OUT;
}
fd_data.aw_fd = data.fd;
#endif
/* mmap to user */
addr_vir = (unsigned long)mmap(NULL, alloc_data.aw_len, \
PROT_READ|PROT_WRITE, MAP_SHARED, fd_data.aw_fd, 0);
if ((unsigned long)MAP_FAILED == addr_vir) {
loge("mmap err, ret %u\n", (unsigned int)addr_vir);
addr_vir = 0;
goto ALLOC_OUT;
}
/* get phy address */
#if defined(CONF_KERNEL_IOMMU)
memset(&iommu_param, 0, sizeof(iommu_param));
iommu_param.fd = fd_data.aw_fd;
ret = ioctl(g_ion_alloc_context->cedar_fd, AW_MEM_ENGINE_REQ, 0);
if (ret) {
loge("ENGINE_REQ err, ret %d\n", ret);
addr_phy = 0;
addr_vir = 0;
goto ALLOC_OUT;
}
ret = ioctl(g_ion_alloc_context->cedar_fd, AW_MEM_GET_IOMMU_ADDR, &iommu_param);
if (ret) {
loge("GET_IOMMU_ADDR err, ret %d\n", ret);
addr_phy = 0;
addr_vir = 0;
goto ALLOC_OUT;
}
addr_phy = iommu_param.iommu_addr;
#else
memset(&phys_data, 0, sizeof(phys_data));
phys_data.handle = alloc_data.handle;
phys_data.size = size;
custom_data.aw_cmd = ION_IOC_SUNXI_PHYS_ADDR;
custom_data.aw_arg = (unsigned long)&phys_data;
ret = ioctl(g_ion_alloc_context->fd, AW_MEM_ION_IOC_CUSTOM, &custom_data);
if (ret) {
loge("ION_IOC_CUSTOM err, ret %d\n", ret);
addr_phy = 0;
addr_vir = 0;
goto ALLOC_OUT;
}
addr_phy = phys_data.phys_addr;
#endif
alloc_buffer = (buffer_node *)malloc(sizeof(buffer_node));
if (alloc_buffer == NULL) {
loge("malloc buffer node failed");
/* unmmap */
ret = munmap((void*)addr_vir, alloc_data.aw_len);
if (ret) {
loge("munmap err, ret %d\n", ret);
}
#if defined(CONF_KERNEL_IOMMU)
ret = ioctl(g_ion_alloc_context->cedar_fd, AW_MEM_ENGINE_REL, 0);
if (ret)
logv("ENGINE_REL failed\n");
ret = ioctl(g_ion_alloc_context->cedar_fd, AW_MEM_FREE_IOMMU_ADDR, &iommu_param);
if (ret)
logv("FREE_IOMMU_ADDR err, ret %d\n", ret);
#endif
/* close dmabuf fd */
close(fd_data.aw_fd);
/* free buffer */
handle_data.handle = alloc_data.handle;
ret = ioctl(g_ion_alloc_context->fd, AW_MEM_ION_IOC_FREE, &handle_data);
if(ret)
loge("ION_IOC_FREE err, ret %d\n", ret);
addr_phy = 0;
addr_vir = 0; /* value of MAP_FAILED is -1, should return 0*/
goto ALLOC_OUT;
}
alloc_buffer->phy = addr_phy;
alloc_buffer->vir = addr_vir;
alloc_buffer->user_virt = addr_vir;
alloc_buffer->size = size;
alloc_buffer->fd_data.handle = fd_data.handle;
alloc_buffer->fd_data.aw_fd = fd_data.aw_fd;
aw_mem_list_add_tail(&alloc_buffer->i_list, &g_ion_alloc_context->list);
#if DEBUG_ION_REF==1
cdx_use_mem += size;
int i = 0;
for (i = 0; i < ION_BUF_LEN; i++) {
if (ion_buf_nodes_test[i].addr == 0
&& ion_buf_nodes_test[i].size == 0) {
ion_buf_nodes_test[i].addr = addr_vir;
ion_buf_nodes_test[i].size = size;
break;
}
}
if (i>= ION_BUF_LEN) {
loge("error, ion buf len is large than [%d]", ION_BUF_LEN);
}
#endif
ALLOC_OUT:
pthread_mutex_unlock(&g_ion_mutex_alloc);
return (void*)addr_vir;
}
根据配置不同,libuapi使用ion设备或者cedar设备来分配内存。