summaryrefslogtreecommitdiff
path: root/src/freedreno/drm/freedreno_ringbuffer.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/freedreno/drm/freedreno_ringbuffer.h')
-rw-r--r--src/freedreno/drm/freedreno_ringbuffer.h159
1 files changed, 99 insertions, 60 deletions
diff --git a/src/freedreno/drm/freedreno_ringbuffer.h b/src/freedreno/drm/freedreno_ringbuffer.h
index 6fc49f72b8e..8442e99b966 100644
--- a/src/freedreno/drm/freedreno_ringbuffer.h
+++ b/src/freedreno/drm/freedreno_ringbuffer.h
@@ -30,7 +30,6 @@
#include <stdio.h>
#include "util/u_atomic.h"
#include "util/u_debug.h"
-#include "util/u_queue.h"
#include "adreno_common.xml.h"
#include "adreno_pm4.xml.h"
@@ -93,39 +92,26 @@ struct fd_ringbuffer *fd_submit_new_ringbuffer(struct fd_submit *submit,
uint32_t size,
enum fd_ringbuffer_flags flags);
-/**
- * Encapsulates submit out-fence(s), which consist of a 'timestamp' (per-
- * pipe (submitqueue) sequence number) and optionally, if requested, an
- * out-fence-fd
- */
-struct fd_submit_fence {
- /**
- * The ready fence is signaled once the submit is actually flushed down
- * to the kernel, and fence/fence_fd are populated. You must wait for
- * this fence to be signaled before reading fence/fence_fd.
- */
- struct util_queue_fence ready;
-
- struct fd_fence fence;
-
- /**
- * Optional dma_fence fd, returned by submit if use_fence_fd is true
- */
- int fence_fd;
- bool use_fence_fd;
-};
-
/* in_fence_fd: -1 for no in-fence, else fence fd
- * out_fence can be NULL if no output fence is required
+ * if use_fence_fd is true the output fence will be dma_fence fd backed
*/
-int fd_submit_flush(struct fd_submit *submit, int in_fence_fd,
- struct fd_submit_fence *out_fence);
+struct fd_fence *fd_submit_flush(struct fd_submit *submit, int in_fence_fd,
+ bool use_fence_fd);
struct fd_ringbuffer;
struct fd_reloc;
struct fd_ringbuffer_funcs {
void (*grow)(struct fd_ringbuffer *ring, uint32_t size);
+
+ /**
+ * Alternative to emit_reloc for the softpin case, where we only need
+ * to track that the bo is used (and not track all the extra info that
+ * the kernel would need to do a legacy reloc.
+ */
+ void (*emit_bo)(struct fd_ringbuffer *ring, struct fd_bo *bo);
+ void (*assert_attached)(struct fd_ringbuffer *ring, struct fd_bo *bo);
+
void (*emit_reloc)(struct fd_ringbuffer *ring, const struct fd_reloc *reloc);
uint32_t (*emit_reloc_ring)(struct fd_ringbuffer *ring,
struct fd_ringbuffer *target, uint32_t cmd_idx);
@@ -154,10 +140,33 @@ struct fd_ringbuffer {
struct fd_ringbuffer *fd_ringbuffer_new_object(struct fd_pipe *pipe,
uint32_t size);
+/*
+ * Helpers for ref/unref with some extra debugging.. unref() returns true if
+ * the object is still live
+ */
+
+static inline void
+ref(int32_t *ref)
+{
+ ASSERTED int32_t count = p_atomic_inc_return(ref);
+ /* We should never see a refcnt transition 0->1, this is a sign of a
+ * zombie coming back from the dead!
+ */
+ assert(count != 1);
+}
+
+static inline bool
+unref(int32_t *ref)
+{
+ int32_t count = p_atomic_dec_return(ref);
+ assert(count != -1);
+ return count == 0;
+}
+
static inline void
fd_ringbuffer_del(struct fd_ringbuffer *ring)
{
- if (!p_atomic_dec_zero(&ring->refcnt))
+ if (--ring->refcnt > 0)
return;
ring->funcs->destroy(ring);
@@ -166,7 +175,7 @@ fd_ringbuffer_del(struct fd_ringbuffer *ring)
static inline struct fd_ringbuffer *
fd_ringbuffer_ref(struct fd_ringbuffer *ring)
{
- p_atomic_inc(&ring->refcnt);
+ ring->refcnt++;
return ring;
}
@@ -175,9 +184,6 @@ fd_ringbuffer_grow(struct fd_ringbuffer *ring, uint32_t ndwords)
{
assert(ring->funcs->grow); /* unsupported on kgsl */
- /* there is an upper bound on IB size, which appears to be 0x0fffff */
- ring->size = MIN2(ring->size << 1, 0x0fffff);
-
ring->funcs->grow(ring, ring->size);
}
@@ -196,13 +202,12 @@ fd_ringbuffer_emit(struct fd_ringbuffer *ring, uint32_t data)
struct fd_reloc {
struct fd_bo *bo;
uint64_t iova;
+ uint64_t orval;
#define FD_RELOC_READ 0x0001
#define FD_RELOC_WRITE 0x0002
#define FD_RELOC_DUMP 0x0004
uint32_t offset;
- uint32_t orlo;
int32_t shift;
- uint32_t orhi; /* used for a5xx+ */
};
/* We always mark BOs for write, instead of tracking it across reloc
@@ -218,6 +223,20 @@ struct fd_reloc {
/* NOTE: relocs are 2 dwords on a5xx+ */
static inline void
+fd_ringbuffer_attach_bo(struct fd_ringbuffer *ring, struct fd_bo *bo)
+{
+ ring->funcs->emit_bo(ring, bo);
+}
+
+static inline void
+fd_ringbuffer_assert_attached(struct fd_ringbuffer *ring, struct fd_bo *bo)
+{
+#ifndef NDEBUG
+ ring->funcs->assert_attached(ring, bo);
+#endif
+}
+
+static inline void
fd_ringbuffer_reloc(struct fd_ringbuffer *ring, const struct fd_reloc *reloc)
{
ring->funcs->emit_reloc(ring, reloc);
@@ -252,10 +271,17 @@ fd_ringbuffer_size(struct fd_ringbuffer *ring)
* do what you expect for growable rb's.. so lets just restrict
* this to stateobj's for now:
*/
- debug_assert(!(ring->flags & FD_RINGBUFFER_GROWABLE));
+ assert(!(ring->flags & FD_RINGBUFFER_GROWABLE));
return offset_bytes(ring->cur, ring->start);
}
+static inline bool
+fd_ringbuffer_empty(struct fd_ringbuffer *ring)
+{
+ return (fd_ringbuffer_cmd_count(ring) == 1) &&
+ (offset_bytes(ring->cur, ring->start) == 0);
+}
+
#define LOG_DWORDS 0
static inline void
@@ -268,40 +294,53 @@ OUT_RING(struct fd_ringbuffer *ring, uint32_t data)
fd_ringbuffer_emit(ring, data);
}
+static inline uint64_t
+__reloc_iova(struct fd_bo *bo, uint32_t offset, uint64_t orval, int32_t shift)
+{
+ uint64_t iova = fd_bo_get_iova(bo) + offset;
+
+ if (shift < 0)
+ iova >>= -shift;
+ else
+ iova <<= shift;
+
+ iova |= orval;
+
+ return iova;
+}
+
/*
* NOTE: OUT_RELOC() is 2 dwords (64b) on a5xx+
*/
-#ifndef __cplusplus
static inline void
OUT_RELOC(struct fd_ringbuffer *ring, struct fd_bo *bo, uint32_t offset,
- uint64_t or, int32_t shift)
+ uint64_t orval, int32_t shift)
{
if (LOG_DWORDS) {
fprintf(stderr, "ring[%p]: OUT_RELOC %04x: %p+%u << %d", ring,
(uint32_t)(ring->cur - ring->start), bo, offset, shift);
}
- debug_assert(offset < fd_bo_size(bo));
-
- uint64_t iova = fd_bo_get_iova(bo) + offset;
-
- if (shift < 0)
- iova >>= -shift;
- else
- iova <<= shift;
-
- iova |= or ;
-
- fd_ringbuffer_reloc(ring, &(struct fd_reloc){
- .bo = bo,
- .iova = iova,
- .offset = offset,
- .orlo = or
- ,
- .shift = shift,
- .orhi = or >> 32,
- });
-}
+ assert(offset < fd_bo_size(bo));
+
+ uint64_t iova = __reloc_iova(bo, offset, orval, shift);
+
+#if FD_BO_NO_HARDPIN
+ uint64_t *cur = (uint64_t *)ring->cur;
+ *cur = iova;
+ ring->cur += 2;
+ fd_ringbuffer_assert_attached(ring, bo);
+#else
+ struct fd_reloc reloc = {
+ .bo = bo,
+ .iova = iova,
+ .orval = orval,
+ .offset = offset,
+ .shift = shift,
+ };
+
+ fd_ringbuffer_reloc(ring, &reloc);
#endif
+}
static inline void
OUT_RB(struct fd_ringbuffer *ring, struct fd_ringbuffer *target)
@@ -345,14 +384,14 @@ static inline void
OUT_PKT4(struct fd_ringbuffer *ring, uint16_t regindx, uint16_t cnt)
{
BEGIN_RING(ring, cnt + 1);
- OUT_RING(ring, pm4_pkt4_hdr(regindx, cnt));
+ OUT_RING(ring, pm4_pkt4_hdr((uint16_t)regindx, (uint16_t)cnt));
}
static inline void
-OUT_PKT7(struct fd_ringbuffer *ring, uint8_t opcode, uint16_t cnt)
+OUT_PKT7(struct fd_ringbuffer *ring, uint32_t opcode, uint32_t cnt)
{
BEGIN_RING(ring, cnt + 1);
- OUT_RING(ring, pm4_pkt7_hdr(opcode, cnt));
+ OUT_RING(ring, pm4_pkt7_hdr((uint8_t)opcode, (uint16_t)cnt));
}
static inline void