From e15972e9af2a593dbf844615eb28365a8b86d0b7 Mon Sep 17 00:00:00 2001 From: "xueman.ruan" Date: Mon, 15 May 2023 16:50:36 +0800 Subject: [PATCH] feat[mpp_dmabuf]: Add dmabuf sync operation sync_begin - cache invalidate, should be called before cpu read sync_end - cache flush, should be called after cpu write MppBuffer sync flow: 1. hw access 2. sync_begin 3. cpu access (read / write) 4. sync_end 5. hw access NOTE: readonly option is faster for read only buffer. Signed-off-by: xueman.ruan Signed-off-by: Herman Chen Change-Id: I253a6139e9bb30808c07075d64f17b5cfad8519a --- inc/mpp_buffer.h | 34 ++++++++- mpp/base/inc/mpp_buffer_impl.h | 4 ++ mpp/base/mpp_buffer.cpp | 75 ++++++++++++++++++- mpp/base/mpp_buffer_impl.cpp | 2 + osal/CMakeLists.txt | 1 + osal/inc/mpp_dmabuf.h | 25 +++++++ osal/mpp_dmabuf.cpp | 127 +++++++++++++++++++++++++++++++++ 7 files changed, 264 insertions(+), 4 deletions(-) create mode 100644 osal/inc/mpp_dmabuf.h create mode 100644 osal/mpp_dmabuf.cpp diff --git a/inc/mpp_buffer.h b/inc/mpp_buffer.h index 652acc87..9c516478 100644 --- a/inc/mpp_buffer.h +++ b/inc/mpp_buffer.h @@ -265,11 +265,29 @@ typedef struct MppBufferInfo_t { #define mpp_buffer_set_offset(buffer, offset) \ mpp_buffer_set_offset_with_caller(buffer, offset, __FUNCTION__) +#define mpp_buffer_sync_begin(buffer) \ + mpp_buffer_sync_begin_f(buffer, 0, __FUNCTION__) +#define mpp_buffer_sync_end(buffer) \ + mpp_buffer_sync_end_f(buffer, 0, __FUNCTION__) +#define mpp_buffer_sync_partial_begin(buffer, offset, length) \ + mpp_buffer_sync_partial_begin_f(buffer, 0, offset, length, __FUNCTION__) +#define mpp_buffer_sync_partial_end(buffer, offset, length) \ + mpp_buffer_sync_partial_end_f(buffer, 0, offset, length, __FUNCTION__) + +#define mpp_buffer_sync_ro_begin(buffer) \ + mpp_buffer_sync_begin_f(buffer, 1, __FUNCTION__) +#define mpp_buffer_sync_ro_end(buffer) \ + mpp_buffer_sync_end_f(buffer, 1, __FUNCTION__) +#define mpp_buffer_sync_ro_partial_begin(buffer, offset, length) \ + mpp_buffer_sync_partial_begin_f(buffer, 1, offset, length, __FUNCTION__) +#define mpp_buffer_sync_ro_partial_end(buffer, offset, length) \ + mpp_buffer_sync_partial_end_f(buffer, 1, offset, length, __FUNCTION__) + #define mpp_buffer_group_get_internal(group, type, ...) \ - mpp_buffer_group_get(group, type, MPP_BUFFER_INTERNAL, MODULE_TAG, __FUNCTION__) + mpp_buffer_group_get(group, (MppBufferType)(type), MPP_BUFFER_INTERNAL, MODULE_TAG, __FUNCTION__) #define mpp_buffer_group_get_external(group, type, ...) \ - mpp_buffer_group_get(group, type, MPP_BUFFER_EXTERNAL, MODULE_TAG, __FUNCTION__) + mpp_buffer_group_get(group, (MppBufferType)(type), MPP_BUFFER_EXTERNAL, MODULE_TAG, __FUNCTION__) #ifdef __cplusplus extern "C" { @@ -302,6 +320,18 @@ MPP_RET mpp_buffer_set_index_with_caller(MppBuffer buffer, int index, const char size_t mpp_buffer_get_offset_with_caller(MppBuffer buffer, const char *caller); MPP_RET mpp_buffer_set_offset_with_caller(MppBuffer buffer, size_t offset, const char *caller); +/** + * @brief MppBuffer cache operation function + * @param buffer The MppBuffer to run the cache operation + * @param ro for readonly option + * @param offset partial sync data start offset + * @param length partial sync data length + */ +MPP_RET mpp_buffer_sync_begin_f(MppBuffer buffer, RK_S32 ro, const char* caller); +MPP_RET mpp_buffer_sync_end_f(MppBuffer buffer, RK_S32 ro, const char* caller); +MPP_RET mpp_buffer_sync_partial_begin_f(MppBuffer buffer, RK_S32 ro, RK_U32 offset, RK_U32 length, const char* caller); +MPP_RET mpp_buffer_sync_partial_end_f(MppBuffer buffer, RK_S32 ro, RK_U32 offset, RK_U32 length, const char* caller); + MPP_RET mpp_buffer_group_get(MppBufferGroup *group, MppBufferType type, MppBufferMode mode, const char *tag, const char *caller); MPP_RET mpp_buffer_group_put(MppBufferGroup group); diff --git a/mpp/base/inc/mpp_buffer_impl.h b/mpp/base/inc/mpp_buffer_impl.h index d0ccd8a1..61443f07 100644 --- a/mpp/base/inc/mpp_buffer_impl.h +++ b/mpp/base/inc/mpp_buffer_impl.h @@ -96,6 +96,9 @@ struct MppBufferImpl_t { size_t offset; size_t length; + /* cacheable flag */ + RK_U32 uncached; + /* * discard: * used for buf on group reset mode @@ -121,6 +124,7 @@ struct MppBufferGroupImpl_t { RK_U32 group_id; MppBufferMode mode; MppBufferType type; + RK_U32 type_flags; /* group status flag */ // buffer force clear mode flag diff --git a/mpp/base/mpp_buffer.cpp b/mpp/base/mpp_buffer.cpp index dd3299b0..64fe53cf 100644 --- a/mpp/base/mpp_buffer.cpp +++ b/mpp/base/mpp_buffer.cpp @@ -20,6 +20,7 @@ #include "mpp_mem.h" #include "mpp_debug.h" +#include "mpp_dmabuf.h" #include "mpp_buffer_impl.h" MPP_RET mpp_buffer_import_with_tag(MppBufferGroup group, MppBufferInfo *info, MppBuffer *buffer, @@ -275,6 +276,77 @@ MPP_RET mpp_buffer_info_get_with_caller(MppBuffer buffer, MppBufferInfo *info, c return MPP_OK; } +static MPP_RET check_buf_need_sync(MppBuffer buffer, MPP_RET *ret, const char *caller) +{ + if (NULL == buffer) { + mpp_err("check buffer found NULL pointer from %s\n", caller); + return MPP_NOK; + } + + MppBufferImpl *impl = (MppBufferImpl *)buffer; + + if (impl->info.fd <= 0) { + mpp_err("check fd found invalid fd %d from %s\n", impl->info.fd, caller); + return MPP_NOK; + } + + /* uncached buffer do not need to sync */ + if (impl->uncached) { + *ret = MPP_OK; + return MPP_NOK; + } + + return MPP_OK; +} + +MPP_RET mpp_buffer_sync_begin_f(MppBuffer buffer, RK_S32 ro, const char* caller) +{ + MPP_RET ret = MPP_NOK; + + if (check_buf_need_sync(buffer, &ret, caller)) + return ret; + + MppBufferImpl *impl = (MppBufferImpl *)buffer; + + return mpp_dmabuf_sync_begin(impl->info.fd, ro, caller); +} + +MPP_RET mpp_buffer_sync_end_f(MppBuffer buffer, RK_S32 ro, const char* caller) +{ + MPP_RET ret = MPP_NOK; + + if (check_buf_need_sync(buffer, &ret, caller)) + return ret; + + MppBufferImpl *impl = (MppBufferImpl *)buffer; + + return mpp_dmabuf_sync_end(impl->info.fd, ro, caller); +} + +MPP_RET mpp_buffer_sync_partial_begin_f(MppBuffer buffer, RK_S32 ro, RK_U32 offset, RK_U32 length, const char* caller) +{ + MPP_RET ret = MPP_NOK; + + if (check_buf_need_sync(buffer, &ret, caller)) + return ret; + + MppBufferImpl *impl = (MppBufferImpl *)buffer; + + return mpp_dmabuf_sync_partial_begin(impl->info.fd, ro, impl->offset + offset, length, caller); +} + +MPP_RET mpp_buffer_sync_partial_end_f(MppBuffer buffer, RK_S32 ro, RK_U32 offset, RK_U32 length, const char* caller) +{ + MPP_RET ret = MPP_NOK; + + if (check_buf_need_sync(buffer, &ret, caller)) + return ret; + + MppBufferImpl *impl = (MppBufferImpl *)buffer; + + return mpp_dmabuf_sync_partial_end(impl->info.fd, ro, impl->offset + offset, length, caller); +} + MPP_RET mpp_buffer_group_get(MppBufferGroup *group, MppBufferType type, MppBufferMode mode, const char *tag, const char *caller) { @@ -375,5 +447,4 @@ MPP_RET mpp_buffer_group_limit_config(MppBufferGroup group, size_t size, RK_S32 p->limit_size = size; p->limit_count = count; return MPP_OK; -} - +} \ No newline at end of file diff --git a/mpp/base/mpp_buffer_impl.cpp b/mpp/base/mpp_buffer_impl.cpp index 3264227d..d86790ef 100644 --- a/mpp/base/mpp_buffer_impl.cpp +++ b/mpp/base/mpp_buffer_impl.cpp @@ -402,6 +402,7 @@ MPP_RET mpp_buffer_create(const char *tag, const char *caller, p->group_id = group->group_id; p->mode = group->mode; p->type = group->type; + p->uncached = (group->type_flags & MPP_BUFFER_FLAGS_CACHABLE) ? 0 : 1; p->logs = group->logs; p->info = *info; @@ -891,6 +892,7 @@ MppBufferGroupImpl *MppBufferService::get_group(const char *tag, const char *cal p->mode = mode; p->type = buffer_type; p->limit = BUFFER_GROUP_SIZE_DEFAULT; + p->type_flags = flags; p->clear_on_exit = (mpp_buffer_debug & MPP_BUF_DBG_CLR_ON_EXIT) ? (1) : (0); p->dump_on_exit = (mpp_buffer_debug & MPP_BUF_DBG_DUMP_ON_EXIT) ? (1) : (0); diff --git a/osal/CMakeLists.txt b/osal/CMakeLists.txt index e4d2b79e..f1eae562 100644 --- a/osal/CMakeLists.txt +++ b/osal/CMakeLists.txt @@ -41,6 +41,7 @@ add_library(osal STATIC mpp_mem_pool.cpp mpp_callback.cpp mpp_eventfd.cpp + mpp_dmabuf.cpp mpp_thread.cpp mpp_compat.cpp mpp_common.cpp diff --git a/osal/inc/mpp_dmabuf.h b/osal/inc/mpp_dmabuf.h new file mode 100644 index 00000000..320c52e7 --- /dev/null +++ b/osal/inc/mpp_dmabuf.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2023 Rockchip Electronics Co., Ltd. + */ + +#ifndef __MPP_DMABUF_H__ +#define __MPP_DMABUF_H__ + +#include "rk_type.h" +#include "mpp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET mpp_dmabuf_sync_begin(RK_S32 fd, RK_S32 ro, const char *caller); +MPP_RET mpp_dmabuf_sync_end(RK_S32 fd, RK_S32 ro, const char *caller); +MPP_RET mpp_dmabuf_sync_partial_begin(RK_S32 fd, RK_S32 ro, RK_U32 offset, RK_U32 length, const char *caller); +MPP_RET mpp_dmabuf_sync_partial_end(RK_S32 fd, RK_S32 ro, RK_U32 offset, RK_U32 length, const char *caller); + +#ifdef __cplusplus +} +#endif + +#endif /* __MPP_DMABUF_H__ */ \ No newline at end of file diff --git a/osal/mpp_dmabuf.cpp b/osal/mpp_dmabuf.cpp new file mode 100644 index 00000000..092c993e --- /dev/null +++ b/osal/mpp_dmabuf.cpp @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2023 Rockchip Electronics Co., Ltd. + */ + +#include +#include +#include +#include + +#include "mpp_log.h" +#include "mpp_dmabuf.h" + +/* SET_NAME and SYNC_PARTIAL are supported after 4.4 kernel */ + +/* Add dma buffer name uapi */ +#ifndef DMA_BUF_SET_NAME +/* 32/64bitness of this uapi was botched in android, there's no difference + * between them in actual uapi, they're just different numbers. + */ +#define DMA_BUF_SET_NAME _IOW(DMA_BUF_BASE, 1, const char *) +#define DMA_BUF_SET_NAME_A _IOW(DMA_BUF_BASE, 1, __u32) +#define DMA_BUF_SET_NAME_B _IOW(DMA_BUF_BASE, 1, __u64) +#endif + +/* Add dma buffer sync partial uapi */ +#ifndef DMA_BUF_IOCTL_SYNC_PARTIAL +struct dma_buf_sync_partial { + __u64 flags; + __u32 offset; + __u32 len; +}; + +#define DMA_BUF_IOCTL_SYNC_PARTIAL _IOW(DMA_BUF_BASE, 2, struct dma_buf_sync_partial) +#endif + +#define MPP_NO_PARTIAL_SUPPORT 25 /* ENOTTY */ + +static RK_U32 has_partial_ops = 1; + +MPP_RET mpp_dmabuf_sync_begin(RK_S32 fd, RK_S32 ro, const char *caller) +{ + struct dma_buf_sync sync; + RK_S32 ret; + + sync.flags = DMA_BUF_SYNC_START | (ro ? DMA_BUF_SYNC_READ : DMA_BUF_SYNC_RW); + + ret = ioctl(fd, DMA_BUF_IOCTL_SYNC, &sync); + if (ret) { + mpp_err_f("ioctl failed for %s from %s\n", strerror(errno), caller); + return MPP_NOK; + } + + return MPP_OK; +} + +MPP_RET mpp_dmabuf_sync_end(RK_S32 fd, RK_S32 ro, const char *caller) +{ + struct dma_buf_sync sync; + RK_S32 ret; + + sync.flags = DMA_BUF_SYNC_END | (ro ? DMA_BUF_SYNC_READ : DMA_BUF_SYNC_RW); + + ret = ioctl(fd, DMA_BUF_IOCTL_SYNC, &sync); + if (ret) { + mpp_err_f("ioctl failed for %s from %s\n", strerror(errno), caller); + return MPP_NOK; + } + + return MPP_OK; +} + +MPP_RET mpp_dmabuf_sync_partial_begin(RK_S32 fd, RK_S32 ro, RK_U32 offset, RK_U32 length, const char *caller) +{ + if (has_partial_ops) { + struct dma_buf_sync_partial sync; + RK_S32 ret; + + sync.flags = DMA_BUF_SYNC_START | (ro ? DMA_BUF_SYNC_READ : DMA_BUF_SYNC_RW); + sync.offset = offset; + sync.len = length; + + ret = ioctl(fd, DMA_BUF_IOCTL_SYNC_PARTIAL, &sync); + if (ret) { + if (errno == MPP_NO_PARTIAL_SUPPORT) { + has_partial_ops = 0; + goto NOT_SUPPORT; + } + + mpp_err_f("ioctl failed for %s from %s\n", strerror(errno), caller); + return MPP_NOK; + } + + return MPP_OK; + } + +NOT_SUPPORT: + return mpp_dmabuf_sync_begin(fd, ro, caller); +} + +MPP_RET mpp_dmabuf_sync_partial_end(RK_S32 fd, RK_S32 ro, RK_U32 offset, RK_U32 length, const char *caller) +{ + if (has_partial_ops) { + struct dma_buf_sync_partial sync; + RK_S32 ret; + + sync.flags = DMA_BUF_SYNC_END | (ro ? DMA_BUF_SYNC_READ : DMA_BUF_SYNC_RW); + sync.offset = offset; + sync.len = length; + + ret = ioctl(fd, DMA_BUF_IOCTL_SYNC_PARTIAL, &sync); + if (ret) { + if (errno == MPP_NO_PARTIAL_SUPPORT) { + has_partial_ops = 0; + goto NOT_SUPPORT; + } + + mpp_err_f("ioctl failed for %s from %s\n", strerror(errno), caller); + return MPP_NOK; + } + + return MPP_OK; + } + +NOT_SUPPORT: + return mpp_dmabuf_sync_end(fd, ro, caller); +} \ No newline at end of file