summaryrefslogtreecommitdiff
path: root/freedreno
diff options
context:
space:
mode:
authorRob Clark <robclark@freedesktop.org>2018-10-09 15:33:39 -0400
committerRob Clark <robclark@freedesktop.org>2018-10-13 17:18:43 -0400
commita8a006192634d1390acf3a09d4edec27084c8507 (patch)
treea684c232c2c5e5ad8b15e47c32b9fa5e012d9b3e /freedreno
parent566b1d9f93e4922edf5b13b80cb46179e9d85802 (diff)
freedreno: expose refcnt'ing on ringbuffers
Move this out of msm_ringbuffer backend so that the gallium driver can refcnt rb's Signed-off-by: Rob Clark <robclark@freedesktop.org>
Diffstat (limited to 'freedreno')
-rwxr-xr-xfreedreno/freedreno-symbol-check1
-rw-r--r--freedreno/freedreno_ringbuffer.c14
-rw-r--r--freedreno/freedreno_ringbuffer.h14
-rw-r--r--freedreno/kgsl/kgsl_ringbuffer.c2
-rw-r--r--freedreno/msm/msm_ringbuffer.c26
5 files changed, 36 insertions, 21 deletions
diff --git a/freedreno/freedreno-symbol-check b/freedreno/freedreno-symbol-check
index 6da9d667..002a3989 100755
--- a/freedreno/freedreno-symbol-check
+++ b/freedreno/freedreno-symbol-check
@@ -49,6 +49,7 @@ fd_ringbuffer_flush
fd_ringbuffer_grow
fd_ringbuffer_new
fd_ringbuffer_new_object
+fd_ringbuffer_ref
fd_ringbuffer_reloc
fd_ringbuffer_reloc2
fd_ringbuffer_reset
diff --git a/freedreno/freedreno_ringbuffer.c b/freedreno/freedreno_ringbuffer.c
index 1fa33b7a..80af736f 100644
--- a/freedreno/freedreno_ringbuffer.c
+++ b/freedreno/freedreno_ringbuffer.c
@@ -71,11 +71,21 @@ fd_ringbuffer_new_object(struct fd_pipe *pipe, uint32_t size)
drm_public void fd_ringbuffer_del(struct fd_ringbuffer *ring)
{
- if (!(ring->flags & FD_RINGBUFFER_OBJECT))
- fd_ringbuffer_reset(ring);
+ if (!atomic_dec_and_test(&ring->refcnt))
+ return;
+
+ fd_ringbuffer_reset(ring);
ring->funcs->destroy(ring);
}
+drm_public struct fd_ringbuffer *
+fd_ringbuffer_ref(struct fd_ringbuffer *ring)
+{
+ STATIC_ASSERT(sizeof(ring->refcnt) <= sizeof(ring->__pad));
+ atomic_inc(&ring->refcnt);
+ return ring;
+}
+
/* ringbuffers which are IB targets should set the toplevel rb (ie.
* the IB source) as it's parent before emitting reloc's, to ensure
* the bookkeeping works out properly.
diff --git a/freedreno/freedreno_ringbuffer.h b/freedreno/freedreno_ringbuffer.h
index 69e7ed99..b2e8024d 100644
--- a/freedreno/freedreno_ringbuffer.h
+++ b/freedreno/freedreno_ringbuffer.h
@@ -53,6 +53,19 @@ struct fd_ringbuffer {
void *user;
uint32_t flags;
+
+ /* This is a bit gross, but we can't use atomic_t in exported
+ * headers. OTOH, we don't need the refcnt to be publicly
+ * visible. The only reason that this struct is exported is
+ * because fd_ringbuffer_emit needs to be something that can
+ * be inlined for performance reasons.
+ */
+ union {
+#ifdef HAS_ATOMIC_OPS
+ atomic_t refcnt;
+#endif
+ uint64_t __pad;
+ };
};
struct fd_ringbuffer * fd_ringbuffer_new(struct fd_pipe *pipe,
@@ -60,6 +73,7 @@ struct fd_ringbuffer * fd_ringbuffer_new(struct fd_pipe *pipe,
struct fd_ringbuffer * fd_ringbuffer_new_object(struct fd_pipe *pipe,
uint32_t size);
+struct fd_ringbuffer *fd_ringbuffer_ref(struct fd_ringbuffer *ring);
void fd_ringbuffer_del(struct fd_ringbuffer *ring);
void fd_ringbuffer_set_parent(struct fd_ringbuffer *ring,
struct fd_ringbuffer *parent);
diff --git a/freedreno/kgsl/kgsl_ringbuffer.c b/freedreno/kgsl/kgsl_ringbuffer.c
index e4fdf342..7361f7d5 100644
--- a/freedreno/kgsl/kgsl_ringbuffer.c
+++ b/freedreno/kgsl/kgsl_ringbuffer.c
@@ -216,6 +216,8 @@ drm_private struct fd_ringbuffer * kgsl_ringbuffer_new(struct fd_pipe *pipe,
}
ring = &kgsl_ring->base;
+ atomic_set(&ring->refcnt, 1);
+
ring->funcs = &funcs;
ring->size = size;
diff --git a/freedreno/msm/msm_ringbuffer.c b/freedreno/msm/msm_ringbuffer.c
index 5a088818..a102ca35 100644
--- a/freedreno/msm/msm_ringbuffer.c
+++ b/freedreno/msm/msm_ringbuffer.c
@@ -29,6 +29,7 @@
#include <assert.h>
#include <inttypes.h>
+#include "xf86atomic.h"
#include "freedreno_ringbuffer.h"
#include "msm_priv.h"
@@ -50,8 +51,6 @@ struct msm_cmd {
struct msm_ringbuffer {
struct fd_ringbuffer base;
- atomic_t refcnt;
-
/* submit ioctl related tables:
* Note that bos and cmds are tracked by the parent ringbuffer, since
* that is global to the submit ioctl call. The reloc's table is tracked
@@ -97,9 +96,6 @@ static inline struct msm_ringbuffer * to_msm_ringbuffer(struct fd_ringbuffer *x)
return (struct msm_ringbuffer *)x;
}
-static void msm_ringbuffer_unref(struct fd_ringbuffer *ring);
-static void msm_ringbuffer_ref(struct fd_ringbuffer *ring);
-
#define INIT_SIZE 0x1000
static pthread_mutex_t idx_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -454,7 +450,7 @@ static int msm_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start
if (msm_cmd->ring->flags & FD_RINGBUFFER_OBJECT) {
/* we could have dropped last reference: */
msm_ring->cmds[i] = NULL;
- msm_ringbuffer_unref(msm_cmd->ring);
+ fd_ringbuffer_del(msm_cmd->ring);
free(U642VOID(cmd->relocs));
}
}
@@ -568,7 +564,7 @@ static uint32_t msm_ringbuffer_emit_reloc_ring(struct fd_ringbuffer *ring,
* destroyed after emitted but before flush, so we must hold a ref:
*/
if (added_cmd && (target->flags & FD_RINGBUFFER_OBJECT)) {
- msm_ringbuffer_ref(target);
+ fd_ringbuffer_ref(target);
}
return size;
@@ -579,13 +575,10 @@ static uint32_t msm_ringbuffer_cmd_count(struct fd_ringbuffer *ring)
return to_msm_ringbuffer(ring)->cmd_count;
}
-static void msm_ringbuffer_unref(struct fd_ringbuffer *ring)
+static void msm_ringbuffer_destroy(struct fd_ringbuffer *ring)
{
struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring);
- if (!atomic_dec_and_test(&msm_ring->refcnt))
- return;
-
flush_reset(ring);
delete_cmds(msm_ring);
@@ -596,12 +589,6 @@ static void msm_ringbuffer_unref(struct fd_ringbuffer *ring)
free(msm_ring);
}
-static void msm_ringbuffer_ref(struct fd_ringbuffer *ring)
-{
- struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring);
- atomic_inc(&msm_ring->refcnt);
-}
-
static const struct fd_ringbuffer_funcs funcs = {
.hostptr = msm_ringbuffer_hostptr,
.flush = msm_ringbuffer_flush,
@@ -610,7 +597,7 @@ static const struct fd_ringbuffer_funcs funcs = {
.emit_reloc = msm_ringbuffer_emit_reloc,
.emit_reloc_ring = msm_ringbuffer_emit_reloc_ring,
.cmd_count = msm_ringbuffer_cmd_count,
- .destroy = msm_ringbuffer_unref,
+ .destroy = msm_ringbuffer_destroy,
};
drm_private struct fd_ringbuffer * msm_ringbuffer_new(struct fd_pipe *pipe,
@@ -633,9 +620,10 @@ drm_private struct fd_ringbuffer * msm_ringbuffer_new(struct fd_pipe *pipe,
list_inithead(&msm_ring->cmd_list);
msm_ring->seqno = ++to_msm_device(pipe->dev)->ring_cnt;
- atomic_set(&msm_ring->refcnt, 1);
ring = &msm_ring->base;
+ atomic_set(&ring->refcnt, 1);
+
ring->funcs = &funcs;
ring->size = size;
ring->pipe = pipe; /* needed in ring_cmd_new() */