diff --git a/freedreno/freedreno_ringbuffer.c b/freedreno/freedreno_ringbuffer.c index de666865..44437906 100644 --- a/freedreno/freedreno_ringbuffer.c +++ b/freedreno/freedreno_ringbuffer.c @@ -56,6 +56,16 @@ void fd_ringbuffer_del(struct fd_ringbuffer *ring) ring->funcs->destroy(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. + */ +void fd_ringbuffer_set_parent(struct fd_ringbuffer *ring, + struct fd_ringbuffer *parent) +{ + ring->parent = parent; +} + void fd_ringbuffer_reset(struct fd_ringbuffer *ring) { uint32_t *start = ring->start; diff --git a/freedreno/freedreno_ringbuffer.h b/freedreno/freedreno_ringbuffer.h index 4c99ea81..a5e1d032 100644 --- a/freedreno/freedreno_ringbuffer.h +++ b/freedreno/freedreno_ringbuffer.h @@ -46,11 +46,14 @@ struct fd_ringbuffer { struct fd_pipe *pipe; struct fd_ringbuffer_funcs *funcs; uint32_t last_timestamp; + struct fd_ringbuffer *parent; }; struct fd_ringbuffer * fd_ringbuffer_new(struct fd_pipe *pipe, uint32_t size); void fd_ringbuffer_del(struct fd_ringbuffer *ring); +void fd_ringbuffer_set_parent(struct fd_ringbuffer *ring, + struct fd_ringbuffer *parent); void fd_ringbuffer_reset(struct fd_ringbuffer *ring); int fd_ringbuffer_flush(struct fd_ringbuffer *ring); uint32_t fd_ringbuffer_timestamp(struct fd_ringbuffer *ring); diff --git a/freedreno/msm/msm_ringbuffer.c b/freedreno/msm/msm_ringbuffer.c index fc5193ae..f3e951f9 100644 --- a/freedreno/msm/msm_ringbuffer.c +++ b/freedreno/msm/msm_ringbuffer.c @@ -44,6 +44,8 @@ struct msm_ringbuffer { /* cmd's table: */ struct drm_msm_gem_submit_cmd *cmds; uint32_t nr_cmds, max_cmds; + struct fd_ringbuffer **rings; + uint32_t nr_rings, max_rings; /* reloc's table: */ struct drm_msm_gem_submit_reloc *relocs; @@ -100,13 +102,21 @@ static uint32_t bo2idx(struct fd_ringbuffer *ring, struct fd_bo *bo, uint32_t fl return idx; } +static int check_cmd_bo(struct fd_ringbuffer *ring, + struct drm_msm_gem_submit_cmd *cmd, struct fd_bo *bo) +{ + struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); + return msm_ring->bos[cmd->submit_idx].handle == bo->handle; +} + static uint32_t offset_bytes(void *end, void *start) { return ((char *)end) - ((char *)start); } static struct drm_msm_gem_submit_cmd * get_cmd(struct fd_ringbuffer *ring, - struct fd_bo *ring_bo, uint32_t submit_offset, uint32_t size, uint32_t type) + struct fd_ringbuffer *target_ring, struct fd_bo *target_bo, + uint32_t submit_offset, uint32_t size, uint32_t type) { struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); struct drm_msm_gem_submit_cmd *cmd = NULL; @@ -117,7 +127,8 @@ static struct drm_msm_gem_submit_cmd * get_cmd(struct fd_ringbuffer *ring, cmd = &msm_ring->cmds[i]; if ((cmd->submit_offset == submit_offset) && (cmd->size == size) && - (cmd->type == type)) + (cmd->type == type) && + check_cmd_bo(ring, cmd, target_bo)) break; cmd = NULL; } @@ -125,9 +136,11 @@ static struct drm_msm_gem_submit_cmd * get_cmd(struct fd_ringbuffer *ring, /* create cmd buf if not: */ if (!cmd) { uint32_t idx = APPEND(msm_ring, cmds); + APPEND(msm_ring, rings); + msm_ring->rings[idx] = target_ring; cmd = &msm_ring->cmds[idx]; cmd->type = type; - cmd->submit_idx = bo2idx(ring, ring_bo, FD_RELOC_READ); + cmd->submit_idx = bo2idx(ring, target_bo, FD_RELOC_READ); cmd->submit_offset = submit_offset; cmd->size = size; } @@ -170,7 +183,7 @@ static int msm_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start submit_offset = offset_bytes(last_start, ring->start); size = offset_bytes(ring->cur, last_start); - get_cmd(ring, ring_bo, submit_offset, size, MSM_SUBMIT_CMD_BUF); + get_cmd(ring, ring, ring_bo, submit_offset, size, MSM_SUBMIT_CMD_BUF); /* needs to be after get_cmd() as that could create bos/cmds table: */ req.bos = VOID2U64(msm_ring->bos), @@ -181,9 +194,10 @@ static int msm_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start /* for each of the cmd's fix up their reloc's: */ for (i = 0; i < msm_ring->nr_cmds; i++) { struct drm_msm_gem_submit_cmd *cmd = &msm_ring->cmds[i]; - uint32_t a = find_next_reloc_idx(msm_ring, 0, cmd->submit_offset); - uint32_t b = find_next_reloc_idx(msm_ring, a, cmd->submit_offset + cmd->size); - cmd->relocs = VOID2U64(&msm_ring->relocs[a]); + struct msm_ringbuffer *target_ring = to_msm_ringbuffer(msm_ring->rings[i]); + uint32_t a = find_next_reloc_idx(target_ring, 0, cmd->submit_offset); + uint32_t b = find_next_reloc_idx(target_ring, a, cmd->submit_offset + cmd->size); + cmd->relocs = VOID2U64(&target_ring->relocs[a]); cmd->nr_relocs = (b > a) ? b - a : 0; } @@ -201,8 +215,13 @@ static int msm_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start fd_bo_del(&msm_bo->base); } + /* for each of the cmd buffers, clear their reloc's: */ + for (i = 0; i < msm_ring->nr_cmds; i++) { + struct msm_ringbuffer *target_ring = to_msm_ringbuffer(msm_ring->rings[i]); + target_ring->nr_relocs = 0; + } + msm_ring->nr_cmds = 0; - msm_ring->nr_relocs = 0; msm_ring->nr_bos = 0; return ret; @@ -212,6 +231,7 @@ static void msm_ringbuffer_emit_reloc(struct fd_ringbuffer *ring, const struct fd_reloc *r) { struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); + struct fd_ringbuffer *parent = ring->parent ? ring->parent : ring; struct msm_bo *msm_bo = to_msm_bo(r->bo); struct drm_msm_gem_submit_reloc *reloc; uint32_t idx = APPEND(msm_ring, relocs); @@ -219,7 +239,7 @@ static void msm_ringbuffer_emit_reloc(struct fd_ringbuffer *ring, reloc = &msm_ring->relocs[idx]; - reloc->reloc_idx = bo2idx(ring, r->bo, r->flags); + reloc->reloc_idx = bo2idx(parent, r->bo, r->flags); reloc->reloc_offset = r->offset; reloc->or = r->or; reloc->shift = r->shift; @@ -236,21 +256,19 @@ static void msm_ringbuffer_emit_reloc(struct fd_ringbuffer *ring, static void msm_ringbuffer_emit_reloc_ring(struct fd_ringbuffer *ring, struct fd_ringmarker *target, struct fd_ringmarker *end) { - struct fd_bo *ring_bo = to_msm_ringbuffer(target->ring)->ring_bo; + struct fd_bo *target_bo = to_msm_ringbuffer(target->ring)->ring_bo; struct drm_msm_gem_submit_cmd *cmd; uint32_t submit_offset, size; submit_offset = offset_bytes(target->cur, target->ring->start); size = offset_bytes(end->cur, target->cur); - assert(target->ring == ring); // TODO - - cmd = get_cmd(ring, ring_bo, submit_offset, size, + cmd = get_cmd(ring, target->ring, target_bo, submit_offset, size, MSM_SUBMIT_CMD_IB_TARGET_BUF); assert(cmd); msm_ringbuffer_emit_reloc(ring, &(struct fd_reloc){ - .bo = ring_bo, + .bo = target_bo, .flags = FD_RELOC_READ, .offset = submit_offset, });