From 41db12df64ace13c98865340b5c076cdf9a99a93 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 21 Jan 2016 15:20:40 +0000 Subject: [PATCH] drm: etnaviv: improve readability of command insertion to ring buffer Improve the readibility of the function which inserts command buffers and other maintanence commands into the GPUs ring buffer. We do this by splitting the ring buffer reservation in two: one chunk for any commands that need to be issued prior to the command buffer, and a separate chunk for commands issued after the buffer. The result is a much more obvious code flow in this function, and localisation of the conditional maintanence commands prior to the command buffer. Signed-off-by: Russell King Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_buffer.c | 95 ++++++++++++------------ 1 file changed, 49 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c index 2a10463a8790..d8d556457427 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c @@ -219,66 +219,41 @@ void etnaviv_buffer_end(struct etnaviv_gpu *gpu) } } +/* Append a command buffer to the ring buffer. */ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event, struct etnaviv_cmdbuf *cmdbuf) { struct etnaviv_cmdbuf *buffer = gpu->buffer; unsigned int waitlink_offset = buffer->user_size - 16; - u32 back, reserve_size, extra_size = 0; + u32 return_target, return_dwords; u32 link_target, link_dwords; if (drm_debug & DRM_UT_DRIVER) etnaviv_buffer_dump(gpu, buffer, 0, 0x50); + link_target = gpu_va(gpu, cmdbuf); + link_dwords = cmdbuf->size / 8; + /* - * If we need to flush the MMU prior to submitting this buffer, we - * will need to append a mmu flush load state, followed by a new + * If we need maintanence prior to submitting this buffer, we will + * need to append a mmu flush load state, followed by a new * link to this buffer - a total of four additional words. */ if (gpu->mmu->need_flush || gpu->switch_context) { + u32 target, extra_dwords; + /* link command */ - extra_size += 2; + extra_dwords = 1; + /* flush command */ if (gpu->mmu->need_flush) - extra_size += 2; + extra_dwords += 1; + /* pipe switch commands */ if (gpu->switch_context) - extra_size += 8; - } - - reserve_size = (6 + extra_size) * 4; - - link_target = etnaviv_buffer_reserve(gpu, buffer, reserve_size / 8); - - /* save offset back into main buffer */ - back = buffer->user_size + reserve_size - 6 * 4; - link_dwords = 6; - - /* Skip over any extra instructions */ - link_target += extra_size * sizeof(u32); - - if (drm_debug & DRM_UT_DRIVER) - pr_info("stream link to 0x%08x @ 0x%08x %p\n", - link_target, gpu_va(gpu, cmdbuf), cmdbuf->vaddr); - - /* jump back from cmd to main buffer */ - CMD_LINK(cmdbuf, link_dwords, link_target); - - link_target = gpu_va(gpu, cmdbuf); - link_dwords = cmdbuf->size / 8; - - if (drm_debug & DRM_UT_DRIVER) { - print_hex_dump(KERN_INFO, "cmd ", DUMP_PREFIX_OFFSET, 16, 4, - cmdbuf->vaddr, cmdbuf->size, 0); - - pr_info("link op: %p\n", buffer->vaddr + waitlink_offset); - pr_info("addr: 0x%08x\n", link_target); - pr_info("back: 0x%08x\n", gpu_va(gpu, buffer) + back); - pr_info("event: %d\n", event); - } + extra_dwords += 4; - if (gpu->mmu->need_flush || gpu->switch_context) { - u32 new_target = gpu_va(gpu, buffer) + buffer->user_size; + target = etnaviv_buffer_reserve(gpu, buffer, extra_dwords); if (gpu->mmu->need_flush) { /* Add the MMU flush */ @@ -302,18 +277,46 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event, CMD_LINK(buffer, link_dwords, link_target); /* Update the link target to point to above instructions */ - link_target = new_target; - link_dwords = extra_size; + link_target = target; + link_dwords = extra_dwords; } - /* trigger event */ + /* + * Append a LINK to the submitted command buffer to return to + * the ring buffer. return_target is the ring target address. + * We need three dwords: event, wait, link. + */ + return_dwords = 3; + return_target = etnaviv_buffer_reserve(gpu, buffer, return_dwords); + CMD_LINK(cmdbuf, return_dwords, return_target); + + /* + * Append event, wait and link pointing back to the wait + * command to the ring buffer. + */ CMD_LOAD_STATE(buffer, VIVS_GL_EVENT, VIVS_GL_EVENT_EVENT_ID(event) | VIVS_GL_EVENT_FROM_PE); - - /* append WAIT/LINK to main buffer */ CMD_WAIT(buffer); - CMD_LINK(buffer, 2, gpu_va(gpu, buffer) + (buffer->user_size - 4)); + CMD_LINK(buffer, 2, return_target + 8); + + if (drm_debug & DRM_UT_DRIVER) + pr_info("stream link to 0x%08x @ 0x%08x %p\n", + return_target, gpu_va(gpu, cmdbuf), cmdbuf->vaddr); + + if (drm_debug & DRM_UT_DRIVER) { + print_hex_dump(KERN_INFO, "cmd ", DUMP_PREFIX_OFFSET, 16, 4, + cmdbuf->vaddr, cmdbuf->size, 0); + + pr_info("link op: %p\n", buffer->vaddr + waitlink_offset); + pr_info("addr: 0x%08x\n", link_target); + pr_info("back: 0x%08x\n", return_target); + pr_info("event: %d\n", event); + } + /* + * Kick off the submitted command by replacing the previous + * WAIT with a link to the address in the ring buffer. + */ etnaviv_buffer_replace_wait(buffer, waitlink_offset, VIV_FE_LINK_HEADER_OP_LINK | VIV_FE_LINK_HEADER_PREFETCH(link_dwords), -- 2.20.1