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>main
parent
566b1d9f93
commit
a8a0061926
|
@ -49,6 +49,7 @@ fd_ringbuffer_flush
|
||||||
fd_ringbuffer_grow
|
fd_ringbuffer_grow
|
||||||
fd_ringbuffer_new
|
fd_ringbuffer_new
|
||||||
fd_ringbuffer_new_object
|
fd_ringbuffer_new_object
|
||||||
|
fd_ringbuffer_ref
|
||||||
fd_ringbuffer_reloc
|
fd_ringbuffer_reloc
|
||||||
fd_ringbuffer_reloc2
|
fd_ringbuffer_reloc2
|
||||||
fd_ringbuffer_reset
|
fd_ringbuffer_reset
|
||||||
|
|
|
@ -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)
|
drm_public void fd_ringbuffer_del(struct fd_ringbuffer *ring)
|
||||||
{
|
{
|
||||||
if (!(ring->flags & FD_RINGBUFFER_OBJECT))
|
if (!atomic_dec_and_test(&ring->refcnt))
|
||||||
fd_ringbuffer_reset(ring);
|
return;
|
||||||
|
|
||||||
|
fd_ringbuffer_reset(ring);
|
||||||
ring->funcs->destroy(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.
|
/* 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 IB source) as it's parent before emitting reloc's, to ensure
|
||||||
* the bookkeeping works out properly.
|
* the bookkeeping works out properly.
|
||||||
|
|
|
@ -53,6 +53,19 @@ struct fd_ringbuffer {
|
||||||
void *user;
|
void *user;
|
||||||
|
|
||||||
uint32_t flags;
|
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,
|
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,
|
struct fd_ringbuffer * fd_ringbuffer_new_object(struct fd_pipe *pipe,
|
||||||
uint32_t size);
|
uint32_t size);
|
||||||
|
|
||||||
|
struct fd_ringbuffer *fd_ringbuffer_ref(struct fd_ringbuffer *ring);
|
||||||
void fd_ringbuffer_del(struct fd_ringbuffer *ring);
|
void fd_ringbuffer_del(struct fd_ringbuffer *ring);
|
||||||
void fd_ringbuffer_set_parent(struct fd_ringbuffer *ring,
|
void fd_ringbuffer_set_parent(struct fd_ringbuffer *ring,
|
||||||
struct fd_ringbuffer *parent);
|
struct fd_ringbuffer *parent);
|
||||||
|
|
|
@ -216,6 +216,8 @@ drm_private struct fd_ringbuffer * kgsl_ringbuffer_new(struct fd_pipe *pipe,
|
||||||
}
|
}
|
||||||
|
|
||||||
ring = &kgsl_ring->base;
|
ring = &kgsl_ring->base;
|
||||||
|
atomic_set(&ring->refcnt, 1);
|
||||||
|
|
||||||
ring->funcs = &funcs;
|
ring->funcs = &funcs;
|
||||||
ring->size = size;
|
ring->size = size;
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include "xf86atomic.h"
|
||||||
#include "freedreno_ringbuffer.h"
|
#include "freedreno_ringbuffer.h"
|
||||||
#include "msm_priv.h"
|
#include "msm_priv.h"
|
||||||
|
|
||||||
|
@ -50,8 +51,6 @@ struct msm_cmd {
|
||||||
struct msm_ringbuffer {
|
struct msm_ringbuffer {
|
||||||
struct fd_ringbuffer base;
|
struct fd_ringbuffer base;
|
||||||
|
|
||||||
atomic_t refcnt;
|
|
||||||
|
|
||||||
/* submit ioctl related tables:
|
/* submit ioctl related tables:
|
||||||
* Note that bos and cmds are tracked by the parent ringbuffer, since
|
* 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
|
* 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;
|
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
|
#define INIT_SIZE 0x1000
|
||||||
|
|
||||||
static pthread_mutex_t idx_lock = PTHREAD_MUTEX_INITIALIZER;
|
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) {
|
if (msm_cmd->ring->flags & FD_RINGBUFFER_OBJECT) {
|
||||||
/* we could have dropped last reference: */
|
/* we could have dropped last reference: */
|
||||||
msm_ring->cmds[i] = NULL;
|
msm_ring->cmds[i] = NULL;
|
||||||
msm_ringbuffer_unref(msm_cmd->ring);
|
fd_ringbuffer_del(msm_cmd->ring);
|
||||||
free(U642VOID(cmd->relocs));
|
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:
|
* destroyed after emitted but before flush, so we must hold a ref:
|
||||||
*/
|
*/
|
||||||
if (added_cmd && (target->flags & FD_RINGBUFFER_OBJECT)) {
|
if (added_cmd && (target->flags & FD_RINGBUFFER_OBJECT)) {
|
||||||
msm_ringbuffer_ref(target);
|
fd_ringbuffer_ref(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
|
@ -579,13 +575,10 @@ static uint32_t msm_ringbuffer_cmd_count(struct fd_ringbuffer *ring)
|
||||||
return to_msm_ringbuffer(ring)->cmd_count;
|
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);
|
struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring);
|
||||||
|
|
||||||
if (!atomic_dec_and_test(&msm_ring->refcnt))
|
|
||||||
return;
|
|
||||||
|
|
||||||
flush_reset(ring);
|
flush_reset(ring);
|
||||||
delete_cmds(msm_ring);
|
delete_cmds(msm_ring);
|
||||||
|
|
||||||
|
@ -596,12 +589,6 @@ static void msm_ringbuffer_unref(struct fd_ringbuffer *ring)
|
||||||
free(msm_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 = {
|
static const struct fd_ringbuffer_funcs funcs = {
|
||||||
.hostptr = msm_ringbuffer_hostptr,
|
.hostptr = msm_ringbuffer_hostptr,
|
||||||
.flush = msm_ringbuffer_flush,
|
.flush = msm_ringbuffer_flush,
|
||||||
|
@ -610,7 +597,7 @@ static const struct fd_ringbuffer_funcs funcs = {
|
||||||
.emit_reloc = msm_ringbuffer_emit_reloc,
|
.emit_reloc = msm_ringbuffer_emit_reloc,
|
||||||
.emit_reloc_ring = msm_ringbuffer_emit_reloc_ring,
|
.emit_reloc_ring = msm_ringbuffer_emit_reloc_ring,
|
||||||
.cmd_count = msm_ringbuffer_cmd_count,
|
.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,
|
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);
|
list_inithead(&msm_ring->cmd_list);
|
||||||
msm_ring->seqno = ++to_msm_device(pipe->dev)->ring_cnt;
|
msm_ring->seqno = ++to_msm_device(pipe->dev)->ring_cnt;
|
||||||
atomic_set(&msm_ring->refcnt, 1);
|
|
||||||
|
|
||||||
ring = &msm_ring->base;
|
ring = &msm_ring->base;
|
||||||
|
atomic_set(&ring->refcnt, 1);
|
||||||
|
|
||||||
ring->funcs = &funcs;
|
ring->funcs = &funcs;
|
||||||
ring->size = size;
|
ring->size = size;
|
||||||
ring->pipe = pipe; /* needed in ring_cmd_new() */
|
ring->pipe = pipe; /* needed in ring_cmd_new() */
|
||||||
|
|
Loading…
Reference in New Issue