Files
mpp/osal/mpp_dmabuf.cpp
Herman Chen 6ce3007994 refactor[allocator]: Refactor allocator flow
1. Allocator api is determined by buffer type.
2. Allocator ctx is determined by both buffer type and buffer flags.
3. All allocator dma_heap / drm / ion / ext_dma should support different
buffer flags.
4. The buffer flag supports cacheable / 32-bit / contig options.
5. Add flags update flow on allocator create process.
6. Add mpp_dmabuf_has_partial_ops to disable dmabuf partial ops when the
kernel driver has bug.

Signed-off-by: Herman Chen <herman.chen@rock-chips.com>
Change-Id: If36a05c6704112cad3ab46861023597ff02bf14c
2023-11-29 09:54:36 +08:00

156 lines
4.1 KiB
C++

/* SPDX-License-Identifier: Apache-2.0 OR MIT */
/*
* Copyright (c) 2023 Rockchip Electronics Co., Ltd.
*/
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/dma-buf.h>
#include "mpp_env.h"
#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;
__attribute__ ((constructor))
void mpp_dmabuf_init(void)
{
/*
* update has_partial_ops by env
* NOTE: When dmaheap is enabled the dmaheap fd partial ops is fine.
* But the drm fd partial ops may have error when kernel version above 4.19
* So we provide the mpp_dmabuf_has_partial_ops env to disable partial ops.
*/
mpp_env_get_u32("mpp_dmabuf_has_partial_ops", &has_partial_ops, has_partial_ops);
}
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);
}
MPP_RET mpp_dmabuf_set_name(RK_S32 fd, const char *name, const char *caller)
{
RK_S32 ret = ioctl(fd, DMA_BUF_SET_NAME, name);
if (ret) {
mpp_err_f("ioctl failed for %s from %s\n", strerror(errno), caller);
return MPP_NOK;
}
return MPP_OK;
}
RK_U32 mpp_dmabuf_sync_partial_support(void)
{
return has_partial_ops;
}