From b7cbb7aaf15b2c905003c8b1d8f7ddbd75eb4ea8 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 26 Aug 2014 14:40:04 +0100 Subject: Add support to import dmabuf fds into etnaviv dmabufs are DMA buffers which can be passed between kernel drivers under the control of userspace by means of a file descriptor. Add support to import dmabufs into etnaviv, creating an etna_bo for them which can be released using the normal methods. Signed-off-by: Russell King --- src/etnaviv/etna_bo.c | 27 ++++++++++++++++++++++++++- src/etnaviv/etna_bo.h | 3 +++ src/etnaviv/viv.c | 38 ++++++++++++++++++++++++++++++++++++++ src/etnaviv/viv.h | 4 ++++ 4 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/etnaviv/etna_bo.c b/src/etnaviv/etna_bo.c index 6777cbe..ea5248b 100644 --- a/src/etnaviv/etna_bo.c +++ b/src/etnaviv/etna_bo.c @@ -41,7 +41,8 @@ enum etna_bo_type { ETNA_BO_TYPE_VIDMEM_EXTERNAL, /* Main vidmem, external handle */ ETNA_BO_TYPE_USERMEM, /* Mapped user memory */ ETNA_BO_TYPE_CONTIGUOUS,/* Contiguous memory */ - ETNA_BO_TYPE_PHYSICAL /* Mmap-ed physical memory */ + ETNA_BO_TYPE_PHYSICAL, /* Mmap-ed physical memory */ + ETNA_BO_TYPE_DMABUF /* dmabuf memory */ }; /* Structure describing a block of video or user memory */ @@ -287,6 +288,22 @@ struct etna_bo *etna_bo_from_name(struct viv_conn *conn, uint32_t name) return mem; } +struct etna_bo *etna_bo_from_dmabuf(struct viv_conn *conn, int fd, int prot) +{ + struct etna_bo *mem = ETNA_CALLOC_STRUCT(etna_bo); + if(mem == NULL) return NULL; + + mem->bo_type = ETNA_BO_TYPE_DMABUF; + + if(viv_map_dmabuf(conn, fd, &mem->usermem_info, &mem->address, prot)!=0) + { + ETNA_FREE(mem); + return NULL; + } + + return mem; +} + struct etna_bo *etna_bo_ref(struct etna_bo *bo) { /* TODO */ @@ -349,6 +366,14 @@ int etna_bo_del(struct viv_conn *conn, struct etna_bo *mem, struct etna_queue *q rv = ETNA_OUT_OF_MEMORY; } break; + case ETNA_BO_TYPE_DMABUF: + if(queue) + { + rv = etna_queue_unmap_user_memory(queue, (void *)1, 1, mem->usermem_info, mem->address); + } else { + rv = viv_unmap_user_memory(conn, (void *)1, 1, mem->usermem_info, mem->address); + } + break; } ETNA_FREE(mem); return rv; diff --git a/src/etnaviv/etna_bo.h b/src/etnaviv/etna_bo.h index 0b65a76..a4f1024 100644 --- a/src/etnaviv/etna_bo.h +++ b/src/etnaviv/etna_bo.h @@ -71,6 +71,9 @@ struct etna_bo *etna_bo_from_fbdev(struct viv_conn *conn, int fd, size_t offset, /* Buffer object from flink name */ struct etna_bo *etna_bo_from_name(struct viv_conn *conn, uint32_t name); +/* Buffer object from dmabuf fd */ +struct etna_bo *etna_bo_from_dmabuf(struct viv_conn *conn, int fd, int prot); + /* Increase reference count */ struct etna_bo *etna_bo_ref(struct etna_bo *bo); diff --git a/src/etnaviv/viv.c b/src/etnaviv/viv.c index 7a9e544..b3f6225 100644 --- a/src/etnaviv/viv.c +++ b/src/etnaviv/viv.c @@ -49,6 +49,27 @@ #endif //#define DEBUG +union rmk_gcabi_header { + uint32_t padding[16]; + struct { + uint32_t zero; +#ifdef GCABI_HAS_HARDWARE_TYPE + uint32_t hwtype; +#endif + uint32_t status; + } v4; +}; + +/* rmk's extension for importing dmabufs */ +struct viv_dmabuf_map { + union rmk_gcabi_header hdr; + uint64_t info; + uint64_t address; + int32_t fd; + uint32_t prot; +}; +#define IOC_GDMABUF_MAP _IOWR('_', 0, struct viv_dmabuf_map) + const char *galcore_device[] = {"/dev/gal3d", "/dev/galcore", "/dev/graphics/galcore", NULL}; #define INTERFACE_SIZE (sizeof(gcsHAL_INTERFACE)) @@ -578,6 +599,23 @@ int viv_free_contiguous(struct viv_conn *conn, size_t bytes, viv_addr_t physical return viv_invoke(conn, &id); } +int viv_map_dmabuf(struct viv_conn *conn, int fd, viv_usermem_t *info, viv_addr_t *address, int prot) +{ + struct viv_dmabuf_map map = { +#ifdef GCABI_HAS_HARDWARE_TYPE + .hdr.v4.hwtype = (gceHARDWARE_TYPE)conn->hw_type, +#endif + .fd = fd, + .prot = prot, + }; + int ret = viv_ioctl(conn, IOC_GDMABUF_MAP, &map, sizeof(map)); + if(ret < 0 || map.hdr.v4.status) + return -1; + *info = VIV_TO_HANDLE(map.info); + *address = map.address; + return VIV_STATUS_OK; +} + int viv_map_user_memory(struct viv_conn *conn, void *memory, size_t size, viv_usermem_t *info, viv_addr_t *address) { gcsHAL_INTERFACE id = { diff --git a/src/etnaviv/viv.h b/src/etnaviv/viv.h index a8daf47..ec044f5 100644 --- a/src/etnaviv/viv.h +++ b/src/etnaviv/viv.h @@ -264,6 +264,10 @@ int viv_free_vidmem(struct viv_conn *conn, viv_node_t node); */ int viv_free_contiguous(struct viv_conn *conn, size_t bytes, viv_addr_t physical, void *logical); +/** Map a dmabuf to GPU memory. + */ +int viv_map_dmabuf(struct viv_conn *conn, int fd, viv_usermem_t *info, viv_addr_t *address, int prot); + /** Map user memory to GPU memory. */ int viv_map_user_memory(struct viv_conn *conn, void *memory, size_t size, viv_usermem_t *info, viv_addr_t *address); -- cgit