summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLucas Stach <l.stach@pengutronix.de>2015-07-02 15:47:49 +0200
committerLucas Stach <l.stach@pengutronix.de>2015-09-10 19:11:30 +0200
commit08d751e9cbe749be83f682fd193e9c0d58c8892d (patch)
tree5cbc050913a3791406579d167501e7a4d662ad6f
parent22fbbde7f16e621b7ac04f086fce4ecfdc853c48 (diff)
downloadxf86-video-armada-for-rmk.tar.gz
xf86-video-armada-for-rmk.tar.xz
etnaviv: port to new kernel interfacefor-rmk
Port the etna-drm backend to use the new kernel interface where command streams are pushed as userspace allocated memory, instead of fixed command buffers. This commit has a lot of room for cleanups and simplifications, like removing the handling of multiple command buffers and the ringbuffer style interface to the command stream (after the submit is finished we can immediately reuse the command stream memory). Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
-rw-r--r--etnaviv/etnadrm.c54
-rw-r--r--etnaviv/etnaviv_drm.h158
2 files changed, 65 insertions, 147 deletions
diff --git a/etnaviv/etnadrm.c b/etnaviv/etnadrm.c
index a2cc27b..0aa9472 100644
--- a/etnaviv/etnadrm.c
+++ b/etnaviv/etnadrm.c
@@ -174,14 +174,6 @@ int viv_open(enum viv_hw_type hw_type, struct viv_conn **out)
version->version_patchlevel,
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.
- */
- if (strcmp(version->date, ETNAVIV_DATE_STR))
- goto error;
-
conn->base_address = 0;
/*
@@ -383,9 +375,6 @@ static struct etna_bo *etna_bo_get(struct viv_conn *conn, size_t bytes,
};
int ret;
- if ((flags & DRM_ETNA_GEM_TYPE_MASK) == DRM_ETNA_GEM_TYPE_CMD)
- req.flags = ETNA_BO_CMDSTREAM;
-
mem = etna_bo_alloc(conn);
if (!mem)
return NULL;
@@ -549,8 +538,8 @@ int etna_free(struct etna_ctx *ctx)
return ETNA_INVALID_ADDR;
for (i = 0; i < NUM_COMMAND_BUFFERS; i++) {
- if (ctx->cmdbufi[i].bo)
- etna_bo_del(ctx->conn, ctx->cmdbufi[i].bo, NULL);
+ if (ctx->cmdbuf[i]->logical)
+ free(ctx->cmdbuf[i]->logical);
if (ctx->cmdbuf[i])
free(ctx->cmdbuf[i]);
}
@@ -576,16 +565,12 @@ int etna_create(struct viv_conn *conn, struct etna_ctx **out)
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;
- buf = etna_bo_map(ctx->cmdbufi[i].bo);
- if (!buf)
+ ctx->cmdbuf[i]->logical = malloc(COMMAND_BUFFER_SIZE);
+ if (!ctx->cmdbuf[i]->logical)
goto error;
-
- ctx->cmdbuf[i]->logical = buf;
xorg_list_init(&ctx->cmdbuf[i]->bo_head);
}
@@ -672,11 +657,10 @@ static int etna_reloc_bo_index(struct etna_ctx *ctx, struct etna_bo *mem,
int etna_flush(struct etna_ctx *ctx, uint32_t *fence_out)
{
- struct drm_etnaviv_gem_submit_cmd cmd;
struct _gcoCMDBUF *buf;
struct drm_etnaviv_gem_submit req;
struct etna_bo *i, *n;
- int index, ret;
+ int ret;
if (!ctx)
return ETNA_INVALID_ADDR;
@@ -688,28 +672,16 @@ int etna_flush(struct etna_ctx *ctx, uint32_t *fence_out)
buf = ctx->cmdbuf[ctx->cur_buf];
- index = etna_reloc_bo_index(ctx, ctx->cmdbufi[ctx->cur_buf].bo,
- ETNA_SUBMIT_BO_READ);
- if (index < 0)
- return ETNA_INTERNAL_ERROR;
-
- 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 = 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.exec_state = ETNA_PIPE_2D;
req.bos = (uintptr_t)buf->bos;
req.nr_bos = buf->num_bos;
+ req.relocs = (uintptr_t)buf->relocs;
+ req.nr_relocs = buf->num_relocs;
+
+ req.stream = (uintptr_t)(buf->logical + buf->offset);
+ req.stream_size = ctx->offset * 4 - buf->offset;
ret = drmCommandWriteRead(ctx->conn->fd, DRM_ETNAVIV_GEM_SUBMIT,
&req, sizeof(req));
@@ -821,5 +793,5 @@ void etna_emit_reloc(struct etna_ctx *ctx, uint32_t buf_offset,
memset(r, 0, sizeof(*r));
r->reloc_idx = index;
r->reloc_offset = offset;
- r->submit_offset = buf_offset * 4;
+ r->submit_offset = buf_offset * 4 - buf->offset;
}
diff --git a/etnaviv/etnaviv_drm.h b/etnaviv/etnaviv_drm.h
index 1818d7a..5f1206b 100644
--- a/etnaviv/etnaviv_drm.h
+++ b/etnaviv/etnaviv_drm.h
@@ -1,6 +1,5 @@
/*
- * Copyright (C) 2013 Red Hat
- * Author: Rob Clark <robdclark@gmail.com>
+ * Copyright (C) 2015 Etnaviv Project
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
@@ -18,16 +17,11 @@
#ifndef __ETNAVIV_DRM_H__
#define __ETNAVIV_DRM_H__
-#define ETNAVIV_DATE_RMK 20130625
-#define ETNAVIV_DATE_PENGUTRONIX 20150302
-#define ETNAVIV_DATE ETNAVIV_DATE_PENGUTRONIX
-
-#include <stddef.h>
-#include "drm.h"
+#include <drm/drm.h>
/* Please note that modifications to all structs defined here are
* subject to backwards-compatibility constraints:
- * 1) Do not use pointers, use uint64_t instead for 32 bit / 64 bit
+ * 1) Do not use pointers, use __u64 instead for 32 bit / 64 bit
* user/kernel compatibility
* 2) Keep fields aligned to their size
* 3) Because of how drm_ioctl() works, we can add new fields at
@@ -38,23 +32,13 @@
* fields.. so that has to be somehow ok.
*/
-#define ETNADRM_PIPE_3D 0x00
-#define ETNADRM_PIPE_2D 0x01
-#define ETNADRM_PIPE_VG 0x02
-
-#if ETNAVIV_DATE == ETNAVIV_DATE_PENGUTRONIX
-#define ETNA_MAX_PIPES 4
-#else
-#define ETNA_MAX_PIPES 3
-#endif
-
/* timeouts are specified in clock-monotonic absolute times (to simplify
* restarting interrupted ioctls). The following struct is logically the
* same as 'struct timespec' but 32/64b ABI safe.
*/
struct drm_etnaviv_timespec {
- int64_t tv_sec; /* seconds */
- int64_t tv_nsec; /* nanoseconds */
+ __s64 tv_sec; /* seconds */
+ __s64 tv_nsec; /* nanoseconds */
};
#define ETNAVIV_PARAM_GPU_MODEL 0x01
@@ -76,39 +60,36 @@ struct drm_etnaviv_timespec {
#define ETNAVIV_PARAM_GPU_INSTRUCTION_COUNT 0x18
#define ETNAVIV_PARAM_GPU_NUM_CONSTANTS 0x19
-//#define MSM_PARAM_GMEM_SIZE 0x02
+#define ETNA_MAX_PIPES 4
struct drm_etnaviv_param {
- uint32_t pipe; /* in, ETNA_PIPE_x */
- uint32_t param; /* in, ETNAVIV_PARAM_x */
- uint64_t value; /* out (get_param) or in (set_param) */
+ __u32 pipe; /* in */
+ __u32 param; /* in, ETNAVIV_PARAM_x */
+ __u64 value; /* out (get_param) or in (set_param) */
};
/*
* GEM buffers:
*/
-#define ETNA_BO_CMDSTREAM 0x00000001
#define ETNA_BO_CACHE_MASK 0x000f0000
/* cache modes */
#define ETNA_BO_CACHED 0x00010000
#define ETNA_BO_WC 0x00020000
#define ETNA_BO_UNCACHED 0x00040000
-#if ETNAVIV_DATE == ETNAVIV_DATE_PENGUTRONIX
/* map flags */
#define ETNA_BO_FORCE_MMU 0x00100000
-#endif
struct drm_etnaviv_gem_new {
- uint64_t size; /* in */
- uint32_t flags; /* in, mask of ETNA_BO_x */
- uint32_t handle; /* out */
+ __u64 size; /* in */
+ __u32 flags; /* in, mask of ETNA_BO_x */
+ __u32 handle; /* out */
};
struct drm_etnaviv_gem_info {
- uint32_t handle; /* in */
- uint32_t pad;
- uint64_t offset; /* out, offset to pass to mmap() */
+ __u32 handle; /* in */
+ __u32 pad;
+ __u64 offset; /* out, offset to pass to mmap() */
};
#define ETNA_PREP_READ 0x01
@@ -116,13 +97,13 @@ struct drm_etnaviv_gem_info {
#define ETNA_PREP_NOSYNC 0x04
struct drm_etnaviv_gem_cpu_prep {
- uint32_t handle; /* in */
- uint32_t op; /* in, mask of ETNA_PREP_x */
+ __u32 handle; /* in */
+ __u32 op; /* in, mask of ETNA_PREP_x */
struct drm_etnaviv_timespec timeout; /* in */
};
struct drm_etnaviv_gem_cpu_fini {
- uint32_t handle; /* in */
+ __u32 handle; /* in */
};
/*
@@ -130,49 +111,15 @@ struct drm_etnaviv_gem_cpu_fini {
*/
/* The value written into the cmdstream is logically:
- *
- * ((relocbuf->gpuaddr + reloc_offset) << shift) | or
- *
- * When we have GPU's w/ >32bit ptrs, it should be possible to deal
- * with this by emit'ing two reloc entries with appropriate shift
- * values. Or a new ETNA_SUBMIT_CMD_x type would also be an option.
+ * relocbuf->gpuaddr + reloc_offset
*
* NOTE that reloc's must be sorted by order of increasing submit_offset,
* otherwise EINVAL.
*/
struct drm_etnaviv_gem_submit_reloc {
- uint32_t submit_offset; /* in, offset from submit_bo */
-#if ETNAVIV_DATE != ETNAVIV_DATE_PENGUTRONIX
- 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 */
-};
-
-/* submit-types:
- * BUF - this cmd buffer is executed normally.
- * IB_TARGET_BUF - this cmd buffer is an IB target. Reloc's are
- * processed normally, but the kernel does not setup an IB to
- * this buffer in the first-level ringbuffer
- * CTX_RESTORE_BUF - only executed if there has been a GPU context
- * switch since the last SUBMIT ioctl
- */
-#define ETNA_SUBMIT_CMD_BUF 0x0001
-#if ETNAVIV_DATE == ETNAVIV_DATE_PENGUTRONIX
-#define ETNA_SUBMIT_CMD_CTX_RESTORE_BUF 0x0002
-#else
-#define ETNA_SUBMIT_CMD_IB_TARGET_BUF 0x0002
-#define ETNA_SUBMIT_CMD_CTX_RESTORE_BUF 0x0003
-#endif
-struct drm_etnaviv_gem_submit_cmd {
- 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 */
+ __u32 submit_offset; /* in, offset from submit_bo */
+ __u32 reloc_idx; /* in, index of reloc_bo buffer */
+ __u64 reloc_offset; /* in, offset from start of reloc_bo */
};
/* Each buffer referenced elsewhere in the cmdstream submit (ie. the
@@ -189,28 +136,28 @@ struct drm_etnaviv_gem_submit_cmd {
#define ETNA_SUBMIT_BO_READ 0x0001
#define ETNA_SUBMIT_BO_WRITE 0x0002
struct drm_etnaviv_gem_submit_bo {
- uint32_t flags; /* in, mask of ETNA_SUBMIT_BO_x */
- uint32_t handle; /* in, GEM handle */
- uint64_t presumed; /* in/out, presumed buffer address */
+ __u32 flags; /* in, mask of ETNA_SUBMIT_BO_x */
+ __u32 handle; /* in, GEM handle */
+ __u64 presumed; /* in/out, presumed buffer address */
};
/* Each cmdstream submit consists of a table of buffers involved, and
* one or more cmdstream buffers. This allows for conditional execution
* (context-restore), and IB buffers needed for per tile/bin draw cmds.
*/
+#define ETNA_PIPE_3D 0x00
+#define ETNA_PIPE_2D 0x01
+#define ETNA_PIPE_VG 0x02
struct drm_etnaviv_gem_submit {
- 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 */
+ __u32 fence; /* out */
+ __u32 pipe; /* in */
+ __u32 exec_state; /* in, initial execution state (ETNA_PIPE_x) */
+ __u32 nr_bos; /* in, number of submit_bo's */
+ __u32 nr_relocs; /* in, number of submit_reloc's */
+ __u32 stream_size; /* in, cmdstream size */
+ __u64 bos; /* in, ptr to array of submit_bo's */
+ __u64 relocs; /* in, ptr to array of submit_reloc's */
+ __u64 stream; /* in, ptr to cmdstream */
};
/* The normal way to synchronize with the GPU is just to CPU_PREP on
@@ -221,18 +168,18 @@ struct drm_etnaviv_gem_submit {
* APIs without requiring a dummy bo to synchronize on.
*/
struct drm_etnaviv_wait_fence {
- uint32_t pipe; /* in, ETNA_PIPE_x */
- uint32_t fence; /* in */
+ __u32 pipe; /* in */
+ __u32 fence; /* in */
struct drm_etnaviv_timespec timeout; /* in */
};
-#define ETNA_USERPTR_READ 0x01
-#define ETNA_USERPTR_WRITE 0x02
+#define ETNA_USERPTR_READ 0x01
+#define ETNA_USERPTR_WRITE 0x02
struct drm_etnaviv_gem_userptr {
- uint64_t user_ptr; /* in, page aligned user pointer */
- uint64_t user_size; /* in, page aligned user size */
- uint32_t flags; /* in, flags */
- uint32_t handle; /* out, non-zero handle */
+ __u64 user_ptr; /* in, page aligned user pointer */
+ __u64 user_size; /* in, page aligned user size */
+ __u32 flags; /* in, flags */
+ __u32 handle; /* out, non-zero handle */
};
struct drm_etnaviv_gem_wait {
@@ -242,7 +189,9 @@ struct drm_etnaviv_gem_wait {
};
#define DRM_ETNAVIV_GET_PARAM 0x00
+/* placeholder:
#define DRM_ETNAVIV_SET_PARAM 0x01
+ */
#define DRM_ETNAVIV_GEM_NEW 0x02
#define DRM_ETNAVIV_GEM_INFO 0x03
#define DRM_ETNAVIV_GEM_CPU_PREP 0x04
@@ -256,14 +205,11 @@ struct drm_etnaviv_gem_wait {
#define DRM_IOCTL_ETNAVIV_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GET_PARAM, struct drm_etnaviv_param)
#define DRM_IOCTL_ETNAVIV_GEM_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_NEW, struct drm_etnaviv_gem_new)
#define DRM_IOCTL_ETNAVIV_GEM_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_INFO, struct drm_etnaviv_gem_info)
-#define DRM_IOCTL_ETNAVIV_GEM_CPU_PREP DRM_IOW (DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_CPU_PREP, struct drm_etnaviv_gem_cpu_prep)
-#define DRM_IOCTL_ETNAVIV_GEM_CPU_FINI DRM_IOW (DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_CPU_FINI, struct drm_etnaviv_gem_cpu_fini)
+#define DRM_IOCTL_ETNAVIV_GEM_CPU_PREP DRM_IOW(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_CPU_PREP, struct drm_etnaviv_gem_cpu_prep)
+#define DRM_IOCTL_ETNAVIV_GEM_CPU_FINI DRM_IOW(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_CPU_FINI, struct drm_etnaviv_gem_cpu_fini)
#define DRM_IOCTL_ETNAVIV_GEM_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_SUBMIT, struct drm_etnaviv_gem_submit)
-#define DRM_IOCTL_ETNAVIV_WAIT_FENCE DRM_IOW (DRM_COMMAND_BASE + DRM_ETNAVIV_WAIT_FENCE, struct drm_etnaviv_wait_fence)
-#define DRM_IOCTL_ETNAVIV_GEM_WAIT DRM_IOW (DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_WAIT, struct drm_etnaviv_gem_wait)
-
-#define __STR(x) #x
-#define _STR(x) __STR(x)
-#define ETNAVIV_DATE_STR _STR(ETNAVIV_DATE)
+#define DRM_IOCTL_ETNAVIV_WAIT_FENCE DRM_IOW(DRM_COMMAND_BASE + DRM_ETNAVIV_WAIT_FENCE, struct drm_etnaviv_wait_fence)
+#define DRM_IOCTL_ETNAVIV_GEM_USERPTR DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_USERPTR, struct drm_etnaviv_gem_userptr)
+#define DRM_IOCTL_ETNAVIV_GEM_WAIT DRM_IOW(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_WAIT, struct drm_etnaviv_gem_wait)
#endif /* __ETNAVIV_DRM_H__ */