summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk@arm.linux.org.uk>2014-08-26 14:40:04 +0100
committerWladimir J. van der Laan <laanwj@gmail.com>2014-08-27 09:01:27 +0200
commitba61a726dcf46ad282227fb7b7d3568441ad09ce (patch)
tree6d5f257bdc7878fd3d8d7fc23b3a189ebac2e45d
parent69da6fbf994d4524f2dc533041f58bfa73abc3a4 (diff)
downloadetna_viv-ba61a726dcf46ad282227fb7b7d3568441ad09ce.tar.gz
etna_viv-ba61a726dcf46ad282227fb7b7d3568441ad09ce.tar.xz
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 c798830..d7acb82 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 8aaf01e..aa097b4 100644
--- a/src/etnaviv/viv.h
+++ b/src/etnaviv/viv.h
@@ -258,6 +258,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);