From 6e138f76b676b8c6dfa744db183776b0668ec272 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 21 Jan 2016 15:20:09 +0000 Subject: drm: etnaviv: extract replacement of WAIT command Extract out the replacement of the WAIT command with some other command. Signed-off-by: Russell King Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_buffer.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c index 7f935e58e4b3..975c11b7fb38 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c @@ -131,6 +131,23 @@ static void etnaviv_buffer_dump(struct etnaviv_gpu *gpu, ptr, len * 4, 0); } +/* + * Safely replace the WAIT of a waitlink with a new command and argument. + * The GPU may be executing this WAIT while we're modifying it, so we have + * to write it in a specific order to avoid the GPU branching to somewhere + * else. 'wl_offset' is the offset to the first byte of the WAIT command. + */ +static void etnaviv_buffer_replace_wait(struct etnaviv_cmdbuf *buffer, + unsigned int wl_offset, u32 cmd, u32 arg) +{ + u32 *lw = buffer->vaddr + wl_offset; + + lw[1] = arg; + mb(); + lw[0] = cmd; + mb(); +} + /* * Ensure that there is space in the command buffer to contiguously write * 'cmd_dwords' 64-bit words into the buffer, wrapping if necessary. @@ -172,7 +189,7 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event, struct etnaviv_cmdbuf *cmdbuf) { struct etnaviv_cmdbuf *buffer = gpu->buffer; - u32 *lw = buffer->vaddr + buffer->user_size - 16; + unsigned int waitlink_offset = buffer->user_size - 16; u32 back, link_target, link_size, reserve_size, extra_size = 0; if (drm_debug & DRM_UT_DRIVER) @@ -219,8 +236,7 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event, print_hex_dump(KERN_INFO, "cmd ", DUMP_PREFIX_OFFSET, 16, 4, cmdbuf->vaddr, cmdbuf->size, 0); - pr_info("link op: %p\n", lw); - pr_info("link addr: %p\n", lw + 1); + 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); @@ -262,12 +278,10 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event, CMD_WAIT(buffer); CMD_LINK(buffer, 2, gpu_va(gpu, buffer) + (buffer->user_size - 4)); - /* Change WAIT into a LINK command; write the address first. */ - *(lw + 1) = link_target; - mb(); - *(lw) = VIV_FE_LINK_HEADER_OP_LINK | - VIV_FE_LINK_HEADER_PREFETCH(link_size); - mb(); + etnaviv_buffer_replace_wait(buffer, waitlink_offset, + VIV_FE_LINK_HEADER_OP_LINK | + VIV_FE_LINK_HEADER_PREFETCH(link_size), + link_target); if (drm_debug & DRM_UT_DRIVER) etnaviv_buffer_dump(gpu, buffer, 0, 0x50); -- cgit v1.2.3