diff options
Diffstat (limited to 'src/freedreno/drm/freedreno_ringbuffer.h')
-rw-r--r-- | src/freedreno/drm/freedreno_ringbuffer.h | 159 |
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 |