linuxOS_D21X/source/artinchip/aic-mpp/ve/common/ve_buffer.c
2024-11-29 16:33:21 +08:00

185 lines
4.2 KiB
C

/*
* Copyright (C) 2020-2022 Artinchip Technology Co. Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* author: <qi.xu@artinchip.com>
* Desc: allocator of physic continuous buffer used by ve
*/
#define LOG_TAG "ve_buffer"
#include <pthread.h>
#include "ve_buffer.h"
#include "mpp_mem.h"
#include "mpp_list.h"
#include "dma_allocator.h"
#include "ve.h"
#include "mpp_log.h"
struct ve_buffer_allocator {
int dma_dev_fd;
int total_count;
int total_size;
int total_max;
pthread_mutex_t lock;
struct mpp_list list;
};
struct ve_buffer_impl {
struct ve_buffer ve_buf;
struct mpp_list list_status;
};
struct ve_buffer_allocator *ve_buffer_allocator_create(enum ve_buffer_type type)
{
struct ve_buffer_allocator *ctx;
ctx = mpp_alloc(sizeof(struct ve_buffer_allocator));
if (!ctx)
return NULL;
memset(ctx, 0, sizeof(struct ve_buffer_allocator));
ctx->dma_dev_fd = dmabuf_device_open();
ctx->total_size = 0;
ctx->total_max = 0;
ctx->total_count = 0;
if (ctx->dma_dev_fd < 0) {
mpp_free(ctx);
loge("mppbuffer ctx init failed!");
return NULL;
}
pthread_mutex_init(&ctx->lock, NULL);
mpp_list_init(&ctx->list);
return ctx;
}
void ve_buffer_allocator_destroy(struct ve_buffer_allocator *ctx)
{
struct ve_buffer_impl *node = NULL;
struct ve_buffer_impl *m = NULL;
if (!ctx)
return;
pthread_mutex_lock(&ctx->lock);
if (!mpp_list_empty(&ctx->list)) {
mpp_list_for_each_entry_safe(node, m, &ctx->list, list_status) {
ctx->total_size -= node->ve_buf.size;
ctx->total_count--;
mpp_list_del_init(&node->list_status);
logw("ve_buffer leak, dma-buf fd: %d, size: %zu", node->ve_buf.fd, node->ve_buf.size);
ve_rm_dma_buf(node->ve_buf.fd, node->ve_buf.phy_addr);
if(node->ve_buf.vir_addr)
dmabuf_munmap(node->ve_buf.vir_addr, node->ve_buf.size);
dmabuf_free(node->ve_buf.fd);
mpp_free(node);
node = NULL;
}
}
mpp_list_del_init(&ctx->list);
pthread_mutex_unlock(&ctx->lock);
if (ctx->total_count > 0) {
loge("mppbuffer ctx deinit, there are %d buffers not released.", ctx->total_count);
}
pthread_mutex_destroy(&ctx->lock);
dmabuf_device_close(ctx->dma_dev_fd);
mpp_free(ctx);
}
struct ve_buffer *ve_buffer_alloc(struct ve_buffer_allocator *ctx, int size, enum ve_buffer_flag flag)
{
struct ve_buffer_impl *buf_impl;
if (!ctx || size <= 0) {
return NULL;
}
buf_impl = (struct ve_buffer_impl*)mpp_alloc(sizeof(struct ve_buffer_impl));
if(!buf_impl) {
return NULL;
}
memset(buf_impl, 0, sizeof(struct ve_buffer_impl));
//* 1. alloc dma-buf
buf_impl->ve_buf.fd = dmabuf_alloc(ctx->dma_dev_fd, size);
if(buf_impl->ve_buf.fd < 0) {
if(buf_impl)
mpp_free(buf_impl);
return NULL;
}
//* 2. mmap
if(flag & ALLOC_NEED_VIR_ADDR)
buf_impl->ve_buf.vir_addr = dmabuf_mmap(buf_impl->ve_buf.fd, size);
//* 3. add dma-buf to ve
ve_add_dma_buf(buf_impl->ve_buf.fd, &buf_impl->ve_buf.phy_addr);
buf_impl->ve_buf.size = size;
pthread_mutex_lock(&ctx->lock);
ctx->total_size += size;
if (ctx->total_size > ctx->total_max)
ctx->total_max = ctx->total_size;
ctx->total_count++;
mpp_list_init(&buf_impl->list_status);
mpp_list_add_tail(&buf_impl->list_status, &ctx->list);
pthread_mutex_unlock(&ctx->lock);
logi("ve_buffer alloc success, fd: %d, size: %zu", buf_impl->ve_buf.fd, buf_impl->ve_buf.size);
return (struct ve_buffer *)buf_impl;
}
int ve_buffer_sync(struct ve_buffer *buf, enum dma_buf_sync_flag flag)
{
if(buf == NULL)
return -1;
return dmabuf_sync(buf->fd, flag);
}
int ve_buffer_sync_range(struct ve_buffer *buf, unsigned char* start_addr, int size, enum dma_buf_sync_flag flag)
{
if(buf == NULL)
return -1;
return dmabuf_sync_range(buf->fd, start_addr, size, flag);
}
void ve_buffer_free(struct ve_buffer_allocator *ctx, struct ve_buffer *buf)
{
struct ve_buffer_impl* buf_impl = (struct ve_buffer_impl*)buf;
if(!ctx || !buf)
return;
logi("ve_buffer_free, fd: %d, size: %zu", buf->fd, buf->size);
pthread_mutex_lock(&ctx->lock);
ctx->total_size -= buf->size;
ctx->total_count--;
mpp_list_del_init(&buf_impl->list_status);
pthread_mutex_unlock(&ctx->lock);
ve_rm_dma_buf(buf->fd, buf->phy_addr);
if(buf->vir_addr)
dmabuf_munmap(buf->vir_addr, buf->size);
dmabuf_free(buf->fd);
mpp_free(buf_impl);
}