summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King <rmk@arm.linux.org.uk>2015-10-21 20:04:13 +0100
committerRussell King <rmk@arm.linux.org.uk>2015-10-21 20:04:13 +0100
commitc4ec4c3b02c75aca840fc9113ddedd794654f158 (patch)
tree31cd9d2095d1628ed513ffc2d5f52a2a66f97a90
parent1fec728c3c5aee345636ad257731dc07387e4353 (diff)
etnaviv: update to work with later revision kernelspace
Lucas has changed the kernel API again, so update the etnadrm backend to cope with these changes. We switch from a statically configured API to a dynamically adapting implementation - we select the API to be used based on the driver date code. Signed-off-by: Russell King <rmk@arm.linux.org.uk>
-rw-r--r--etnaviv/etnadrm.c215
-rw-r--r--etnaviv/etnaviv_drm.h50
2 files changed, 212 insertions, 53 deletions
diff --git a/etnaviv/etnadrm.c b/etnaviv/etnadrm.c
index 85afb3b..6e6262a 100644
--- a/etnaviv/etnadrm.c
+++ b/etnaviv/etnadrm.c
@@ -27,6 +27,7 @@ struct etna_viv_conn {
struct viv_conn conn;
struct bo_cache cache;
unsigned int etnadrm_pipe;
+ unsigned int api_date;
};
static struct etna_viv_conn *to_etna_viv_conn(struct viv_conn *conn)
@@ -180,12 +181,14 @@ int viv_open(enum viv_hw_type hw_type, struct viv_conn **out)
version->date);
/*
- * Check the date code. We have two differing APIs, and their
- * only identifying feature is the date code. 20150302 is
- * Pengutronix's version.
+ * Read the driver date code, which will tell us which API to use.
+ * We have three APIs at present, which can be identified via the
+ * date code:
+ * 20130625 and earlier are the original APIs
+ * 20150302 is revision 1 of Pengutronix's API
+ * 20150910 is revision 2 of Pengutronix's API
*/
- if (strcmp(version->date, ETNAVIV_DATE_STR))
- goto error;
+ ec->api_date = atoi(version->date);
conn->base_address = 0;
@@ -593,7 +596,7 @@ struct _gcoCMDBUF {
unsigned offset;
unsigned num_relocs;
unsigned max_relocs;
- struct drm_etnaviv_gem_submit_reloc *relocs;
+ void *relocs;
unsigned num_bos;
unsigned max_bos;
struct drm_etnaviv_gem_submit_bo *bos;
@@ -632,20 +635,37 @@ int etna_create(struct viv_conn *conn, struct etna_ctx **out)
ctx->cur_buf = ETNA_NO_BUFFER;
for (i = 0; i < NUM_COMMAND_BUFFERS; i++) {
- void *buf;
-
ctx->cmdbuf[i] = calloc(1, sizeof *ctx->cmdbuf[i]);
- ctx->cmdbufi[i].bo = etna_bo_new(conn, COMMAND_BUFFER_SIZE,
- DRM_ETNA_GEM_TYPE_CMD);
- if (!ctx->cmdbuf[i] || !ctx->cmdbufi[i].bo)
+ if (!ctx->cmdbuf[i])
goto error;
+ xorg_list_init(&ctx->cmdbuf[i]->bo_head);
+ }
- buf = etna_bo_map(ctx->cmdbufi[i].bo);
- if (!buf)
- goto error;
+ if (to_etna_viv_conn(ctx->conn)->api_date < ETNAVIV_DATE_PENGUTRONIX2) {
+ void *buf;
- ctx->cmdbuf[i]->logical = buf;
- xorg_list_init(&ctx->cmdbuf[i]->bo_head);
+ for (i = 0; i < NUM_COMMAND_BUFFERS; i++) {
+ ctx->cmdbufi[i].bo = etna_bo_new(conn, COMMAND_BUFFER_SIZE,
+ DRM_ETNA_GEM_TYPE_CMD);
+ if (!ctx->cmdbufi[i].bo)
+ goto error;
+
+ buf = etna_bo_map(ctx->cmdbufi[i].bo);
+ if (!buf)
+ goto error;
+
+ ctx->cmdbuf[i]->logical = buf;
+ }
+ } else {
+ void *buf;
+
+ for (i = 0; i < NUM_COMMAND_BUFFERS; i++) {
+ buf = malloc(COMMAND_BUFFER_SIZE);
+ if (!buf)
+ goto error;
+
+ ctx->cmdbuf[i]->logical = buf;
+ }
}
*out = ctx;
@@ -729,29 +749,58 @@ static int etna_reloc_bo_index(struct etna_ctx *ctx, struct etna_bo *mem,
return mem->bo_idx;
}
-int etna_flush(struct etna_ctx *ctx, uint32_t *fence_out)
+static int etna_do_flush_r20130625(struct etna_ctx *ctx, uint32_t *fence_out)
{
- struct drm_etnaviv_gem_submit_cmd cmd;
+ struct drm_etnaviv_gem_submit_cmd_r20130625 cmd;
+ struct drm_etnaviv_gem_submit_r20130625 req;
struct _gcoCMDBUF *buf;
- struct drm_etnaviv_gem_submit req;
- struct etna_bo *i, *n;
int index, ret;
- if (!ctx)
- return ETNA_INVALID_ADDR;
-
- if (ctx->cur_buf == ETNA_CTX_BUFFER)
+ index = etna_reloc_bo_index(ctx, ctx->cmdbufi[ctx->cur_buf].bo,
+ ETNA_SUBMIT_BO_READ);
+ if (index < 0)
return ETNA_INTERNAL_ERROR;
- if (ctx->cur_buf == ETNA_NO_BUFFER)
- return 0;
buf = ctx->cmdbuf[ctx->cur_buf];
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.type = ETNA_SUBMIT_CMD_BUF;
+ cmd.submit_idx = index;
+ cmd.submit_offset = buf->offset;
+ cmd.size = ctx->offset * 4 - buf->offset;
+ cmd.relocs = (uintptr_t)buf->relocs;
+ cmd.nr_relocs = buf->num_relocs;
+
+ memset(&req, 0, sizeof(req));
+ req.pipe = to_etna_viv_conn(ctx->conn)->etnadrm_pipe;
+ req.cmds = (uintptr_t)&cmd;
+ req.nr_cmds = 1;
+ req.bos = (uintptr_t)buf->bos;
+ req.nr_bos = buf->num_bos;
+
+ ret = drmCommandWriteRead(ctx->conn->fd, DRM_ETNAVIV_GEM_SUBMIT,
+ &req, sizeof(req));
+
+ if (ret == 0 && fence_out)
+ *fence_out = req.fence;
+
+ return ret;
+}
+
+static int etna_do_flush_r20150302(struct etna_ctx *ctx, uint32_t *fence_out)
+{
+ struct drm_etnaviv_gem_submit_cmd_r20150302 cmd;
+ struct drm_etnaviv_gem_submit_r20150302 req;
+ struct _gcoCMDBUF *buf;
+ int ret, index;
+
index = etna_reloc_bo_index(ctx, ctx->cmdbufi[ctx->cur_buf].bo,
ETNA_SUBMIT_BO_READ);
if (index < 0)
return ETNA_INTERNAL_ERROR;
+ buf = ctx->cmdbuf[ctx->cur_buf];
+
memset(&cmd, 0, sizeof(cmd));
cmd.type = ETNA_SUBMIT_CMD_BUF;
cmd.submit_idx = index;
@@ -762,9 +811,7 @@ int etna_flush(struct etna_ctx *ctx, uint32_t *fence_out)
memset(&req, 0, sizeof(req));
req.pipe = to_etna_viv_conn(ctx->conn)->etnadrm_pipe;
-#if ETNAVIV_DATE == ETNAVIV_DATE_PENGUTRONIX
req.exec_state = ETNADRM_PIPE_2D;
-#endif
req.cmds = (uintptr_t)&cmd;
req.nr_cmds = 1;
req.bos = (uintptr_t)buf->bos;
@@ -772,15 +819,68 @@ int etna_flush(struct etna_ctx *ctx, uint32_t *fence_out)
ret = drmCommandWriteRead(ctx->conn->fd, DRM_ETNAVIV_GEM_SUBMIT,
&req, sizeof(req));
+ if (ret == 0 && fence_out)
+ *fence_out = req.fence;
+
+ return ret;
+}
+
+static int etna_do_flush_r20150910(struct etna_ctx *ctx, uint32_t *fence_out)
+{
+ struct drm_etnaviv_gem_submit_r20150910 req;
+ struct _gcoCMDBUF *buf;
+ int ret;
+
+ buf = ctx->cmdbuf[ctx->cur_buf];
+
+ memset(&req, 0, sizeof(req));
+ req.pipe = to_etna_viv_conn(ctx->conn)->etnadrm_pipe;
+ req.exec_state = ETNADRM_PIPE_2D;
+ req.nr_bos = buf->num_bos;
+ req.nr_relocs = buf->num_relocs;
+ req.stream_size = ctx->offset * 4 - buf->offset;
+ req.bos = (uintptr_t)buf->bos;
+ req.relocs = (uintptr_t)buf->relocs;
+ req.stream = (uintptr_t)buf->logical + buf->offset;
+
+ ret = drmCommandWriteRead(ctx->conn->fd, DRM_ETNAVIV_GEM_SUBMIT,
+ &req, sizeof(req));
+ if (ret == 0 && fence_out)
+ *fence_out = req.fence;
+
+ return ret;
+}
+
+int etna_flush(struct etna_ctx *ctx, uint32_t *fence_out)
+{
+ struct _gcoCMDBUF *buf;
+ struct etna_bo *i, *n;
+ unsigned int api_date;
+ int ret;
+
+ if (!ctx)
+ return ETNA_INVALID_ADDR;
+
+ if (ctx->cur_buf == ETNA_CTX_BUFFER)
+ return ETNA_INTERNAL_ERROR;
+ if (ctx->cur_buf == ETNA_NO_BUFFER)
+ return 0;
+
+ api_date = to_etna_viv_conn(ctx->conn)->api_date;
+ if (api_date < ETNAVIV_DATE_PENGUTRONIX)
+ ret = etna_do_flush_r20130625(ctx, fence_out);
+ else if (api_date < ETNAVIV_DATE_PENGUTRONIX2)
+ ret = etna_do_flush_r20150302(ctx, fence_out);
+ else
+ ret = etna_do_flush_r20150910(ctx, fence_out);
+
if (ret) {
fprintf(stderr, "drmCommandWriteRead failed: %s\n",
strerror(errno));
return ETNA_INTERNAL_ERROR;
}
- if (fence_out)
- *fence_out = req.fence;
-
+ buf = ctx->cmdbuf[ctx->cur_buf];
xorg_list_for_each_entry_safe(i, n, &buf->bo_head, node) {
xorg_list_del(&i->node);
i->bo_idx = -1;
@@ -860,29 +960,54 @@ int _etna_reserve_internal(struct etna_ctx *ctx, size_t n)
void etna_emit_reloc(struct etna_ctx *ctx, uint32_t buf_offset,
struct etna_bo *mem, uint32_t offset, Bool write)
{
+ unsigned int api_date = to_etna_viv_conn(ctx->conn)->api_date;
struct _gcoCMDBUF *buf = ctx->cmdbuf[ctx->cur_buf];
- struct drm_etnaviv_gem_submit_reloc *r;
+ union reloc {
+ struct drm_etnaviv_gem_submit_reloc latest;
+ struct drm_etnaviv_gem_submit_reloc_r20130625 r20130625;
+ } reloc;
uint32_t flags;
- int index;
+ size_t size;
+ int index, n;
+
+ flags = write ? ETNA_SUBMIT_BO_WRITE : ETNA_SUBMIT_BO_READ;
+
+ index = etna_reloc_bo_index(ctx, mem, flags);
+ assert(index >= 0);
+
+ if (api_date < ETNAVIV_DATE_PENGUTRONIX) {
+ size = sizeof(reloc.r20130625);
+ memset(&reloc, 0, size);
+ reloc.r20130625.reloc_idx = index;
+ reloc.r20130625.reloc_offset = offset;
+ reloc.r20130625.submit_offset = buf_offset * 4;
+ } else if (api_date < ETNAVIV_DATE_PENGUTRONIX2) {
+ size = sizeof(reloc.latest);
+ memset(&reloc, 0, size);
+ reloc.latest.reloc_idx = index;
+ reloc.latest.reloc_offset = offset;
+ reloc.latest.submit_offset = buf_offset * 4;
+ } else {
+ size = sizeof(reloc.latest);
+ memset(&reloc, 0, size);
+ reloc.latest.reloc_idx = index;
+ reloc.latest.reloc_offset = offset;
+ reloc.latest.submit_offset = buf_offset * 4 - buf->offset;
+ }
+
+ n = buf->num_relocs++;
+ if (buf->num_relocs > buf->max_relocs) {
+ void *r;
- if (++buf->num_relocs > buf->max_relocs) {
if (buf->max_relocs)
buf->max_relocs += 16;
else
buf->max_relocs = 8;
- r = realloc(buf->relocs, buf->max_relocs * sizeof *r);
+
+ r = realloc(buf->relocs, buf->max_relocs * size);
assert(r != NULL);
buf->relocs = r;
}
- flags = write ? ETNA_SUBMIT_BO_WRITE : ETNA_SUBMIT_BO_READ;
-
- index = etna_reloc_bo_index(ctx, mem, flags);
- assert(index >= 0);
-
- r = &buf->relocs[buf->num_relocs - 1];
- memset(r, 0, sizeof(*r));
- r->reloc_idx = index;
- r->reloc_offset = offset;
- r->submit_offset = buf_offset * 4;
+ memcpy((char *)buf->relocs + n * size, &reloc, size);
}
diff --git a/etnaviv/etnaviv_drm.h b/etnaviv/etnaviv_drm.h
index 1818d7a..2d2a926 100644
--- a/etnaviv/etnaviv_drm.h
+++ b/etnaviv/etnaviv_drm.h
@@ -20,6 +20,7 @@
#define ETNAVIV_DATE_RMK 20130625
#define ETNAVIV_DATE_PENGUTRONIX 20150302
+#define ETNAVIV_DATE_PENGUTRONIX2 20150910
#define ETNAVIV_DATE ETNAVIV_DATE_PENGUTRONIX
#include <stddef.h>
@@ -142,10 +143,15 @@ struct drm_etnaviv_gem_cpu_fini {
*/
struct drm_etnaviv_gem_submit_reloc {
uint32_t submit_offset; /* in, offset from submit_bo */
-#if ETNAVIV_DATE != ETNAVIV_DATE_PENGUTRONIX
+ uint32_t reloc_idx; /* in, index of reloc_bo buffer */
+ uint64_t reloc_offset; /* in, offset from start of reloc_bo */
+};
+
+/* Original API */
+struct drm_etnaviv_gem_submit_reloc_r20130625 {
+ uint32_t submit_offset; /* in, offset from submit_bo */
uint32_t or; /* in, value OR'd with result */
int32_t shift; /* in, amount of left shift (can be negative) */
-#endif
uint32_t reloc_idx; /* in, index of reloc_bo buffer */
uint64_t reloc_offset; /* in, offset from start of reloc_bo */
};
@@ -165,7 +171,17 @@ struct drm_etnaviv_gem_submit_reloc {
#define ETNA_SUBMIT_CMD_IB_TARGET_BUF 0x0002
#define ETNA_SUBMIT_CMD_CTX_RESTORE_BUF 0x0003
#endif
-struct drm_etnaviv_gem_submit_cmd {
+struct drm_etnaviv_gem_submit_cmd_r20150302 {
+ uint32_t type; /* in, one of ETNA_SUBMIT_CMD_x */
+ uint32_t submit_idx; /* in, index of submit_bo cmdstream buffer */
+ uint32_t submit_offset; /* in, offset into submit_bo */
+ uint32_t size; /* in, cmdstream size */
+ uint32_t pad;
+ uint32_t nr_relocs; /* in, number of submit_reloc's */
+ uint64_t relocs; /* in, ptr to array of submit_reloc's */
+};
+
+struct drm_etnaviv_gem_submit_cmd_r20130625 {
uint32_t type; /* in, one of ETNA_SUBMIT_CMD_x */
uint32_t submit_idx; /* in, index of submit_bo cmdstream buffer */
uint32_t submit_offset; /* in, offset into submit_bo */
@@ -198,17 +214,35 @@ struct drm_etnaviv_gem_submit_bo {
* one or more cmdstream buffers. This allows for conditional execution
* (context-restore), and IB buffers needed for per tile/bin draw cmds.
*/
-struct drm_etnaviv_gem_submit {
+struct drm_etnaviv_gem_submit_r20150910 {
+ uint32_t fence; /* out */
+ uint32_t pipe; /* in, ETNA_PIPE_x */
+ uint32_t exec_state; /* in, initial execution state (ETNA_PIPE_x) */
+ uint32_t nr_bos; /* in, number of submit_bo's */
+ uint32_t nr_relocs; /* in, number of submit_reloc's */
+ uint32_t stream_size; /* in, cmdstream size */
+ uint64_t bos; /* in, ptr to array of submit_bo's */
+ uint64_t relocs; /* in, ptr to array of submit_reloc's */
+ uint64_t stream; /* in, ptr to cmdstream */
+};
+
+struct drm_etnaviv_gem_submit_r20150302 {
uint32_t pipe; /* in, ETNA_PIPE_x */
-#if ETNAVIV_DATE == ETNAVIV_DATE_PENGUTRONIX
uint32_t exec_state;
-#endif
uint32_t fence; /* out */
uint32_t nr_bos; /* in, number of submit_bo's */
uint32_t nr_cmds; /* in, number of submit_cmd's */
-#if ETNAVIV_DATE == ETNAVIV_DATE_PENGUTRONIX
uint32_t pad;
-#endif
+ uint64_t bos; /* in, ptr to array of submit_bo's */
+ uint64_t cmds; /* in, ptr to array of submit_cmd's */
+};
+
+/* Original submission structure */
+struct drm_etnaviv_gem_submit_r20130625 {
+ uint32_t pipe; /* in, ETNA_PIPE_x */
+ uint32_t fence; /* out */
+ uint32_t nr_bos; /* in, number of submit_bo's */
+ uint32_t nr_cmds; /* in, number of submit_cmd's */
uint64_t bos; /* in, ptr to array of submit_bo's */
uint64_t cmds; /* in, ptr to array of submit_cmd's */
};