Is there a real use case to make use of multiple command buffers per one submit ioctl? I have removed it from my kernel tree.
2015-04-02 17:29 GMT+02:00 Lucas Stach l.stach@pengutronix.de:
From: Russell King rmk+kernel@arm.linux.org.uk
etnaviv_buffer_queue() could not handle multiple command buffers. We can handle this trivially by adapting the existing code - we record where we want to link to, and walk the submitted command buffers in reverse order, appending a LINK command to the previous target.
This also means that we conveniently end up with the address and size to link to when changing the previous WAIT command.
Signed-off-by: Russell King rmk+kernel@arm.linux.org.uk
drivers/staging/etnaviv/etnaviv_buffer.c | 45 +++++++++++++++++--------------- 1 file changed, 24 insertions(+), 21 deletions(-)
diff --git a/drivers/staging/etnaviv/etnaviv_buffer.c b/drivers/staging/etnaviv/etnaviv_buffer.c index 945af22db3f1..be2b02ce9a46 100644 --- a/drivers/staging/etnaviv/etnaviv_buffer.c +++ b/drivers/staging/etnaviv/etnaviv_buffer.c @@ -148,7 +148,7 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event, struct et struct etnaviv_gem_object *buffer = to_etnaviv_bo(gpu->buffer); struct etnaviv_gem_object *cmd; u32 *lw = buffer->vaddr + ((buffer->offset - 4) * 4);
u32 back;
u32 back, link_target, link_size; u32 i; if (drm_debug & DRM_UT_DRIVER)
@@ -156,6 +156,8 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event, struct et
/* save offset back into main buffer */ back = buffer->offset;
link_target = buffer->paddr + buffer->offset * 4;
link_size = 6; /* trigger event */ CMD_LOAD_STATE(buffer, VIVS_GL_EVENT, VIVS_GL_EVENT_EVENT_ID(event) | VIVS_GL_EVENT_FROM_PE);
@@ -165,27 +167,28 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event, struct et CMD_LINK(buffer, 2, buffer->paddr + ((buffer->offset - 1) * 4));
/* update offset for every cmd stream */
for (i = 0; i < submit->nr_cmds; i++)
submit->cmd[i].obj->offset = submit->cmd[i].offset +
submit->cmd[i].size;
for (i = submit->nr_cmds; i--; ) {
cmd = submit->cmd[i].obj;
/* TODO: inter-connect all cmd buffers */
cmd->offset = submit->cmd[i].offset + submit->cmd[i].size;
/* jump back from last cmd to main buffer */
cmd = submit->cmd[submit->nr_cmds - 1].obj;
CMD_LINK(cmd, 4, buffer->paddr + (back * 4));
if (drm_debug & DRM_UT_DRIVER)
pr_info("stream link from buffer %u to 0x%08x @ 0x%08x %p\n",
i, link_target,
cmd->paddr + cmd->offset * 4,
cmd->vaddr + cmd->offset * 4);
/* update the size */
for (i = 0; i < submit->nr_cmds; i++)
submit->cmd[i].size = submit->cmd[i].obj->offset -
submit->cmd[i].offset;
/* jump back from last cmd to main buffer */
CMD_LINK(cmd, link_size, link_target);
if (drm_debug & DRM_UT_DRIVER) {
pr_info("stream link @ 0x%08x\n",
cmd->paddr + ((cmd->offset - 1) * 4));
pr_info("stream link @ %p\n",
cmd->vaddr + ((cmd->offset - 1) * 4));
/* update the size */
submit->cmd[i].size = cmd->offset - submit->cmd[i].offset;
link_target = cmd->paddr + submit->cmd[i].offset * 4;
link_size = submit->cmd[i].size * 2;
}
if (drm_debug & DRM_UT_DRIVER) { for (i = 0; i < submit->nr_cmds; i++) { struct etnaviv_gem_object *obj = submit->cmd[i].obj;
@@ -195,16 +198,16 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event, struct et
pr_info("link op: %p\n", lw); pr_info("link addr: %p\n", lw + 1);
pr_info("addr: 0x%08x\n", submit->cmd[0].obj->paddr);
pr_info("addr: 0x%08x\n", link_target); pr_info("back: 0x%08x\n", buffer->paddr + (back * 4)); pr_info("event: %d\n", event); } /* Change WAIT into a LINK command; write the address first. */
i = VIV_FE_LINK_HEADER_OP_LINK | VIV_FE_LINK_HEADER_PREFETCH(submit->cmd[0].size * 2);
*(lw + 1) = submit->cmd[0].obj->paddr + submit->cmd[0].offset * 4;
*(lw + 1) = link_target; mb();
*(lw)= i;
*(lw) = VIV_FE_LINK_HEADER_OP_LINK |
VIV_FE_LINK_HEADER_PREFETCH(link_size); mb(); if (drm_debug & DRM_UT_DRIVER)
-- 2.1.4
-- Christian Gmeiner, MSc