drm: etnaviv: improve readability of command insertion to ring buffer
authorRussell King <rmk+kernel@arm.linux.org.uk>
Thu, 21 Jan 2016 15:20:40 +0000 (15:20 +0000)
committerLucas Stach <l.stach@pengutronix.de>
Mon, 7 Mar 2016 14:36:59 +0000 (15:36 +0100)
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 <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
drivers/gpu/drm/etnaviv/etnaviv_buffer.c

index 2a10463a87905ceb60339ee644dd9a8438876621..d8d5564574276421a21e032d6b85beff32e3f41e 100644 (file)
@@ -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),