[drm]: use mmap() in native way for GNU Linux target

The "[drm]: fix runtime error for 32bit library" is hack way,
it won't work at GNU Linux platform. Also you need to check
_FILE_OFFSET_BITS and _LARGEFILE64_SOURCE before use the
mmap64().

For the normal mmap() with glibc, we only request to
check offset is aligned with page size but not the lenght.
But that doesn't apply for the memory from the drm device,
also the android use a different rule.

I decide not to map all the buffer to cpu at beginning
since most of them won't be access by the cpu.

Change-Id: I74ac7b5b63d45029cae076985a3d0b4526c62bbc
Signed-off-by: Randy Li <randy.li@rock-chips.com>
This commit is contained in:
Randy Li
2017-02-24 16:03:55 +08:00
committed by Herman Chen
parent 8083d5ca60
commit e0a1d6579d
3 changed files with 83 additions and 116 deletions

View File

@@ -44,6 +44,37 @@ static RK_U32 drm_debug = 0;
#define drm_dbg(flag, fmt, ...) _mpp_dbg_f(drm_debug, flag, fmt, ## __VA_ARGS__)
#if defined(ANDROID) && !defined(__LP64__)
#include <errno.h> /* for EINVAL */
extern void *__mmap2(void *, size_t, int, int, int, size_t);
static inline void *drm_mmap(void *addr, size_t length, int prot, int flags,
int fd, loff_t offset)
{
/* offset must be aligned to 4096 (not necessarily the page size) */
if (offset & 4095) {
errno = EINVAL;
return MAP_FAILED;
}
return __mmap2(addr, length, prot, flags, fd, (size_t) (offset >> 12));
}
# define drm_munmap(addr, length) \
munmap(addr, length)
#else
/* assume large file support exists */
# define drm_mmap(addr, length, prot, flags, fd, offset) \
mmap(addr, length, prot, flags, fd, offset)
# define drm_munmap(addr, length) \
munmap(addr, length)
#endif
typedef struct {
RK_U32 alignment;
RK_S32 drm_device;
@@ -65,28 +96,6 @@ static int drm_ioctl(int fd, int req, void *arg)
return ret;
}
static void* drm_mmap(int fd, size_t len, int prot, int flags, loff_t offset)
{
static unsigned long pagesize_mask = 0;
func_mmap64 fp_mmap64 = mpp_rt_get_mmap64();
if (fd < 0)
return NULL;
if (!pagesize_mask)
pagesize_mask = sysconf(_SC_PAGESIZE) - 1;
len = (len + pagesize_mask) & ~pagesize_mask;
if (offset & 4095)
return NULL;
if (fp_mmap64)
return fp_mmap64(NULL, len, prot, flags, fd, offset);
return NULL;
}
static int drm_handle_to_fd(int fd, RK_U32 handle, int *map_fd, RK_U32 flags)
{
int ret;
@@ -100,9 +109,8 @@ static int drm_handle_to_fd(int fd, RK_U32 handle, int *map_fd, RK_U32 flags)
return -EINVAL;
ret = drm_ioctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &dph);
if (ret < 0) {
if (ret < 0)
return ret;
}
*map_fd = dph.fd;
@@ -130,48 +138,12 @@ static int drm_fd_to_handle(int fd, int map_fd, RK_U32 *handle, RK_U32 flags)
}
*handle = dph.handle;
drm_dbg(DRM_FUNCTION, "get handle %d", *handle);
return ret;
}
static int drm_map(int fd, RK_U32 handle, size_t length, int prot,
int flags, unsigned char **ptr, int *map_fd)
{
int ret;
struct drm_mode_map_dumb dmmd;
memset(&dmmd, 0, sizeof(dmmd));
dmmd.handle = handle;
if (map_fd == NULL)
return -EINVAL;
if (ptr == NULL)
return -EINVAL;
ret = drm_handle_to_fd(fd, handle, map_fd, 0);
drm_dbg(DRM_FUNCTION, "drm_map fd %d", *map_fd);
if (ret < 0)
return ret;
ret = drm_ioctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &dmmd);
if (ret < 0) {
close(*map_fd);
return ret;
}
drm_dbg(DRM_FUNCTION, "dev fd %d length %d", fd, length);
*ptr = drm_mmap(fd, length, prot, flags, dmmd.offset);
if (*ptr == MAP_FAILED) {
close(*map_fd);
*map_fd = -1;
mpp_err("mmap failed: %s\n", strerror(errno));
return -errno;
}
return ret;
}
static int drm_alloc(int fd, size_t len, size_t align, RK_U32 *handle)
{
int ret;
@@ -269,13 +241,14 @@ static MPP_RET os_allocator_drm_alloc(void *ctx, MppBufferInfo *info)
return ret;
}
drm_dbg(DRM_FUNCTION, "handle %d", (RK_U32)((intptr_t)info->hnd));
ret = drm_map(p->drm_device, (RK_U32)((intptr_t)info->hnd), info->size,
PROT_READ | PROT_WRITE, MAP_SHARED,
(unsigned char **)&info->ptr, &info->fd);
ret = drm_handle_to_fd(p->drm_device, (RK_U32)((intptr_t)info->hnd),
&info->fd, 0);
if (ret) {
mpp_err("os_allocator_drm_alloc drm_map failed ret %d\n", ret);
mpp_err("os_allocator_drm_alloc handle_to_fd failed ret %d\n", ret);
return ret;
}
info->ptr = NULL;
return ret;
}
@@ -287,29 +260,15 @@ static MPP_RET os_allocator_drm_import(void *ctx, MppBufferInfo *data)
memset(&dmmd, 0, sizeof(dmmd));
drm_dbg(DRM_FUNCTION, "enter");
// NOTE: do not use the original buffer fd,
// use dup fd to avoid unexpected external fd close
data->fd = dup(data->fd);
ret = drm_fd_to_handle(p->drm_device, data->fd, (RK_U32 *)&data->hnd, 0);
drm_dbg(DRM_FUNCTION, "get handle %d", (intptr_t)(data->hnd));
dmmd.handle = (intptr_t)data->hnd;
ret = drm_ioctl(p->drm_device, DRM_IOCTL_MODE_MAP_DUMB, &dmmd);
if (ret < 0)
return ret;
drm_dbg(DRM_FUNCTION, "dev fd %d length %d", p->drm_device, data->size);
data->ptr = drm_mmap(p->drm_device, data->size, PROT_READ | PROT_WRITE,
MAP_SHARED, dmmd.offset);
if (data->ptr == MAP_FAILED) {
mpp_err("mmap failed: %s\n", strerror(errno));
return -errno;
}
ret = drm_handle_to_fd(p->drm_device, (RK_U32)((intptr_t)data->hnd),
&data->fd, 0);
data->ptr = NULL;
drm_dbg(DRM_FUNCTION, "leave");
return ret;
@@ -326,11 +285,11 @@ static MPP_RET os_allocator_drm_free(void *ctx, MppBufferInfo *data)
p = (allocator_ctx_drm *)ctx;
if (data->ptr) {
munmap(data->ptr, data->size);
drm_munmap(data->ptr, data->size);
data->ptr = NULL;
}
close(data->fd);
return drm_free(p->drm_device, (RK_U32)((intptr_t)data->hnd));
}
@@ -346,13 +305,52 @@ static MPP_RET os_allocator_drm_close(void *ctx)
p = (allocator_ctx_drm *)ctx;
drm_dbg(DRM_FUNCTION, "close fd %d", p->drm_device);
ret = close(p->drm_device);
mpp_free(p);
if (ret < 0)
return (MPP_RET) - errno;
return MPP_OK;
}
static MPP_RET os_allocator_drm_mmap(void *ctx, MppBufferInfo *data)
{
allocator_ctx_drm *p;
MPP_RET ret = MPP_OK;
if (NULL == ctx) {
mpp_err("os_allocator_close do not accept NULL input\n");
return MPP_ERR_NULL_PTR;
}
p = (allocator_ctx_drm *)ctx;
if (NULL == ctx)
return MPP_ERR_NULL_PTR;
if (NULL == data->ptr) {
struct drm_mode_map_dumb dmmd;
memset(&dmmd, 0, sizeof(dmmd));
dmmd.handle = (RK_U32)(intptr_t)data->hnd;
ret = drm_ioctl(p->drm_device, DRM_IOCTL_MODE_MAP_DUMB, &dmmd);
if (ret) {
mpp_err("map_dumb failed: %s\n", strerror(ret));
return ret;
}
data->ptr = drm_mmap(NULL, data->size, PROT_READ | PROT_WRITE,
MAP_SHARED, p->drm_device, dmmd.offset);
if (data->ptr == MAP_FAILED) {
mpp_err("mmap failed: %s\n", strerror(errno));
data->ptr = NULL;
return -errno;
}
}
return ret;
}
os_allocator allocator_drm = {
.open = os_allocator_drm_open,
.close = os_allocator_drm_close,
@@ -360,5 +358,5 @@ os_allocator allocator_drm = {
.free = os_allocator_drm_free,
.import = os_allocator_drm_import,
.release = os_allocator_drm_free,
.mmap = NULL,
.mmap = os_allocator_drm_mmap,
};

View File

@@ -19,13 +19,6 @@
#include "mpp_common.h"
/*
* Runtime function detection is for rockchip software platform detection
*/
typedef void *(*func_mmap64)(void* addr, size_t length, int prot, int flags,
int fd, off_t offset);
#ifdef __cplusplus
extern "C" {
#endif
@@ -35,8 +28,6 @@ extern "C" {
* runtime environment. This is usefull on product environemnt.
*/
func_mmap64 mpp_rt_get_mmap64();
#ifdef __cplusplus
}
#endif

View File

@@ -19,25 +19,3 @@
#endif
#include "mpp_runtime.h"
static func_mmap64 mpp_rt_mmap64 = NULL;
func_mmap64 mpp_rt_get_mmap64()
{
#ifdef RKPLATFORM
static RK_U32 once = 1;
if (once) {
void *libc_hdl = dlopen("libc", RTLD_LAZY);
if (libc_hdl) {
mpp_rt_mmap64 = (func_mmap64)dlsym(libc_hdl, "mmap64");
dlclose(libc_hdl);
}
once = 0;
}
#endif
return mpp_rt_mmap64;
}