summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King <rmk@arm.linux.org.uk>2014-08-26 14:40:04 +0100
committerRussell King <rmk@arm.linux.org.uk>2014-08-26 19:07:44 +0100
commitb7cbb7aaf15b2c905003c8b1d8f7ddbd75eb4ea8 (patch)
tree1c71d767cdcbd3cb57e7dd9636fa435a2239ed92
parent5411a9c5e97a6f3f18393f0bc18ca62ce1630b81 (diff)
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 <rmk@arm.linux.org.uk>
-rw-r--r--src/etnaviv/etna_bo.c27
-rw-r--r--src/etnaviv/etna_bo.h3
-rw-r--r--src/etnaviv/viv.c38
-rw-r--r--src/etnaviv/viv.h4
4 files changed, 71 insertions, 1 deletions
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);