Files
2026-08-24 10:03:24 +08:00

208 lines
6.0 KiB
C

// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
/*
* Copyright (C) 2025 Amlogic, Inc. All rights reserved
*/
#include <IONmem.h>
#include <errno.h>
#include <fcntl.h>
#include <ion/ion.h>
#include <linux/ion.h>
#include <linux/ion_4.12.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
//#define __DEBUG
#ifdef __DEBUG
#define __D(fmt, args...) printf("ionmem debug: " fmt, ##args)
#else
#define __D(fmt, args...)
#endif
#define __E(fmt, args...) printf("ionmem error: " fmt, ##args)
int ion_mem_init(void)
{
int ion_fd = -1;
ion_fd = ion_open();
if (ion_fd < 0) {
__E("%s failed: '%s'\n", __func__, strerror(errno));
return -1;
}
__D("%s, ion_fd=%d\n", __func__, ion_fd);
return ion_fd;
}
int ion_mem_alloc_fd(int ion_fd, size_t size, IONMEM_AllocParams *params, unsigned int flag,
unsigned int alloc_hmask)
{
int ret = -1;
int num_heaps = 0;
unsigned int heap_mask = 0;
if (ion_query_heap_cnt(ion_fd, &num_heaps) >= 0) {
__D("num_heaps=%d\n", num_heaps);
struct ion_heap_data *const heaps =
(struct ion_heap_data *)malloc(num_heaps * sizeof(struct ion_heap_data));
if (heaps != NULL && num_heaps) {
if (ion_query_get_heaps(ion_fd, num_heaps, heaps) >= 0) {
for (int i = 0; i != num_heaps; ++i) {
__D("heaps[%d].type=%d, heap_id=%d name:%s\n", i, heaps[i].type, heaps[i].heap_id, heaps[i].name);
if ((1 << heaps[i].type) == alloc_hmask) {
heap_mask = 1 << heaps[i].heap_id;
__D("%d, m=%x, 1<<heap_id=%x, heap_mask=%x, name=%s, "
"alloc_hmask=%x\n",
heaps[i].type, 1 << heaps[i].type, heaps[i].heap_id, heap_mask,
heaps[i].name, alloc_hmask);
break;
}
}
}
free(heaps);
if (heap_mask)
ret = ion_alloc_fd(ion_fd, size, 0, heap_mask, flag, &params->mImageFd);
else
__D("don't find match heap!!\n");
} else {
if (heaps)
free(heaps);
__E("heaps is NULL or no heaps,num_heaps=%d\n", num_heaps);
}
} else {
__E("query_heap_cnt fail! no ion heaps for alloc!!!\n");
}
if (ret < 0) {
__D("ion_alloc failed, errno=%d\n", ret);
return -ENOMEM;
}
return ret;
}
unsigned long ion_mem_alloc(int ion_fd, size_t size, IONMEM_AllocParams *params, bool cache_flag)
{
int ret = -1;
int legacy_ion = 0;
unsigned flag = 0;
legacy_ion = ion_is_legacy(ion_fd);
if (cache_flag) {
flag = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC;
}
__D("%s, cache=%d, bytes=%ld, legacy_ion=%d, flag=0x%x\n", __func__, cache_flag, size,
legacy_ion, flag);
if (legacy_ion == 1) {
if (!cache_flag) {
ret = ion_alloc(ion_fd, size, 0, ION_HEAP_TYPE_DMA_MASK, flag, &params->mIonHnd);
if (ret < 0)
ret = ion_alloc(ion_fd, size, 0, ION_HEAP_CARVEOUT_MASK, flag, &params->mIonHnd);
}
if (ret < 0) {
ret = ion_alloc(ion_fd, size, 0, 1 << ION_HEAP_TYPE_CUSTOM, flag, &params->mIonHnd);
if (ret < 0) {
__E("%s failed, errno=%d\n", __func__, errno);
return -ENOMEM;
}
}
ret = ion_share(ion_fd, params->mIonHnd, &params->mImageFd);
if (ret < 0) {
__E("ion_share failed, errno=%d\n", errno);
ion_free(ion_fd, params->mIonHnd);
return -EINVAL;
}
ion_free(ion_fd, params->mIonHnd);
} else {
flag |= ION_FLAG_EXTEND_MESON_HEAP;
ret = ion_mem_alloc_fd(ion_fd, size, params, flag, ION_HEAP_TYPE_DMA_MASK);
if (ret < 0)
ret = ion_mem_alloc_fd(ion_fd, size, params, flag, ION_HEAP_CARVEOUT_MASK);
if (ret < 0)
ret = ion_mem_alloc_fd(ion_fd, size, params, flag, ION_HEAP_TYPE_CUSTOM);
if (ret < 0)
ret = ion_mem_alloc_fd(ion_fd, size, params, flag, ION_HEAP_SYSTEM_CONTIG_MASK);
if (ret < 0) {
__E("%s failed, errno=%d\n", __func__, errno);
return -ENOMEM;
}
}
__D("%s okay done!, legacy_ion=%d\n", __func__, legacy_ion);
__D("%s, shared_fd=%d\n", __func__, params->mImageFd);
return ret;
}
int ion_mem_free(int ion_fd, IONMEM_AllocParams *params)
{
__D("%s free fd:%d ionhnd:%d mImageFd:%d\n", __func__, ion_fd, params->mIonHnd, params->mImageFd);
if (ion_is_legacy(ion_fd)) {
ion_free(ion_fd, params->mIonHnd);
__D("%s, ion_free\n", __func__);
} else {
close(params->mImageFd);
__D("%s, close\n", __func__);
}
return 0;
}
int ion_mem_sync_cache(int ion_fd, int shared_fd)
{
int legacy_ion = 0;
legacy_ion = ion_is_legacy(ion_fd);
if (!legacy_ion)
return 0;
if (ion_fd >= 0 && shared_fd >= 0) {
if (ion_sync_fd(ion_fd, shared_fd)) {
__E("ion_mem_sync_cache err!\n");
return -1;
}
} else {
__E("ion_mem_sync_cache err!\n");
return -1;
}
return 0;
}
#if 0
int ion_mem_invalid_cache(int ion_fd, int shared_fd)
{
int legacy_ion = 0;
legacy_ion = ion_is_legacy(ion_fd);
if (!legacy_ion)
return 0;
if (ion_fd >= 0 && shared_fd >= 0) {
if (ion_cache_invalid(ion_fd, shared_fd)) {
__E("ion_mem_invalid_cache err!\n");
return -1;
}
} else {
__E("ion_mem_invalid_cache err!\n");
return -1;
}
return 0;
}
#endif
void ion_mem_exit(int ion_fd)
{
int ret = -1;
__D("exit: %s, ion_fd=%d\n", __func__, ion_fd);
ret = ion_close(ion_fd);
if (ret < 0) {
__E("%s err (%s)! ion_fd=%d\n", __func__, strerror(errno), ion_fd);
return;
}
}