Commit 6e138f76 authored by Russell King's avatar Russell King Committed by Lucas Stach

drm: etnaviv: extract replacement of WAIT command

Extract out the replacement of the WAIT command with some other command.
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: default avatarLucas Stach <l.stach@pengutronix.de>
parent 584a13c6
...@@ -131,6 +131,23 @@ static void etnaviv_buffer_dump(struct etnaviv_gpu *gpu, ...@@ -131,6 +131,23 @@ static void etnaviv_buffer_dump(struct etnaviv_gpu *gpu,
ptr, len * 4, 0); 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 * Ensure that there is space in the command buffer to contiguously write
* 'cmd_dwords' 64-bit words into the buffer, wrapping if necessary. * '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, ...@@ -172,7 +189,7 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event,
struct etnaviv_cmdbuf *cmdbuf) struct etnaviv_cmdbuf *cmdbuf)
{ {
struct etnaviv_cmdbuf *buffer = gpu->buffer; 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; u32 back, link_target, link_size, reserve_size, extra_size = 0;
if (drm_debug & DRM_UT_DRIVER) if (drm_debug & DRM_UT_DRIVER)
...@@ -219,8 +236,7 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event, ...@@ -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, print_hex_dump(KERN_INFO, "cmd ", DUMP_PREFIX_OFFSET, 16, 4,
cmdbuf->vaddr, cmdbuf->size, 0); cmdbuf->vaddr, cmdbuf->size, 0);
pr_info("link op: %p\n", lw); pr_info("link op: %p\n", buffer->vaddr + waitlink_offset);
pr_info("link addr: %p\n", lw + 1);
pr_info("addr: 0x%08x\n", link_target); pr_info("addr: 0x%08x\n", link_target);
pr_info("back: 0x%08x\n", gpu_va(gpu, buffer) + back); pr_info("back: 0x%08x\n", gpu_va(gpu, buffer) + back);
pr_info("event: %d\n", event); pr_info("event: %d\n", event);
...@@ -262,12 +278,10 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event, ...@@ -262,12 +278,10 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event,
CMD_WAIT(buffer); CMD_WAIT(buffer);
CMD_LINK(buffer, 2, gpu_va(gpu, buffer) + (buffer->user_size - 4)); CMD_LINK(buffer, 2, gpu_va(gpu, buffer) + (buffer->user_size - 4));
/* Change WAIT into a LINK command; write the address first. */ etnaviv_buffer_replace_wait(buffer, waitlink_offset,
*(lw + 1) = link_target; VIV_FE_LINK_HEADER_OP_LINK |
mb(); VIV_FE_LINK_HEADER_PREFETCH(link_size),
*(lw) = VIV_FE_LINK_HEADER_OP_LINK | link_target);
VIV_FE_LINK_HEADER_PREFETCH(link_size);
mb();
if (drm_debug & DRM_UT_DRIVER) if (drm_debug & DRM_UT_DRIVER)
etnaviv_buffer_dump(gpu, buffer, 0, 0x50); etnaviv_buffer_dump(gpu, buffer, 0, 0x50);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment