drm/msm/adreno: Add ringbuffer data to the GPU state
authorJordan Crouse <jcrouse@codeaurora.org>
Tue, 24 Jul 2018 16:33:29 +0000 (10:33 -0600)
committerRob Clark <robdclark@gmail.com>
Mon, 30 Jul 2018 12:50:03 +0000 (08:50 -0400)
Add the contents of each ringbuffer to the GPU state and dump the
data in the crash file encoded with ascii85. To save space only
the used portions of the ringbuffer are dumped.

Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
Documentation/gpu/msm-crash-dump.rst
drivers/gpu/drm/msm/adreno/adreno_gpu.c
drivers/gpu/drm/msm/msm_gpu.h

index 75ab1d541c037190ffde22109d72c8aa1905605c..35e87004e006e66b110fb9a2ae345cd76d52e1f2 100644 (file)
@@ -59,6 +59,13 @@ ringbuffer
        wptr
                The current write pointer (wptr) for the ringbuffer.
 
+       size
+               Maximum size of the ringbuffer programmed in the hardware.
+
+       data
+               The contents of the ring encoded as ascii85.  Only the used
+               portions of the ring will be printed.
+
 registers
        Set of registers values. Each entry is on its own line enclosed
        by brackets { }.
index c7a998d9dc855ee6c805de1375c8b030612da0b6..808d4fc9c4a15120106dbede461587b105494016 100644 (file)
@@ -17,6 +17,7 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/ascii85.h>
 #include <linux/pm_opp.h>
 #include "adreno_gpu.h"
 #include "msm_gem.h"
@@ -383,11 +384,29 @@ struct msm_gpu_state *adreno_gpu_state_get(struct msm_gpu *gpu)
        do_gettimeofday(&state->time);
 
        for (i = 0; i < gpu->nr_rings; i++) {
+               int size = 0, j;
+
                state->ring[i].fence = gpu->rb[i]->memptrs->fence;
                state->ring[i].iova = gpu->rb[i]->iova;
                state->ring[i].seqno = gpu->rb[i]->seqno;
                state->ring[i].rptr = get_rptr(adreno_gpu, gpu->rb[i]);
                state->ring[i].wptr = get_wptr(gpu->rb[i]);
+
+               /* Copy at least 'wptr' dwords of the data */
+               size = state->ring[i].wptr;
+
+               /* After wptr find the last non zero dword to save space */
+               for (j = state->ring[i].wptr; j < MSM_GPU_RINGBUFFER_SZ >> 2; j++)
+                       if (gpu->rb[i]->start[j])
+                               size = j + 1;
+
+               if (size) {
+                       state->ring[i].data = kmalloc(size << 2, GFP_KERNEL);
+                       if (state->ring[i].data) {
+                               memcpy(state->ring[i].data, gpu->rb[i]->start, size << 2);
+                               state->ring[i].data_size = size << 2;
+                       }
+               }
        }
 
        /* Count the number of registers */
@@ -418,9 +437,13 @@ struct msm_gpu_state *adreno_gpu_state_get(struct msm_gpu *gpu)
 
 static void adreno_gpu_state_destroy(struct kref *kref)
 {
+       int i;
        struct msm_gpu_state *state = container_of(kref,
                struct msm_gpu_state, ref);
 
+       for (i = 0; i < ARRAY_SIZE(state->ring); i++)
+               kfree(state->ring[i].data);
+
        kfree(state->comm);
        kfree(state->cmd);
        kfree(state->registers);
@@ -461,6 +484,22 @@ void adreno_show(struct msm_gpu *gpu, struct msm_gpu_state *state,
                drm_printf(p, "    retired-fence: %d\n", state->ring[i].fence);
                drm_printf(p, "    rptr: %d\n", state->ring[i].rptr);
                drm_printf(p, "    wptr: %d\n", state->ring[i].wptr);
+               drm_printf(p, "    size: %d\n", MSM_GPU_RINGBUFFER_SZ);
+
+               if (state->ring[i].data && state->ring[i].data_size) {
+                       u32 *ptr = (u32 *) state->ring[i].data;
+                       char out[ASCII85_BUFSZ];
+                       long len = ascii85_encode_len(state->ring[i].data_size);
+                       int j;
+
+                       drm_printf(p, "    data: !!ascii85 |\n");
+                       drm_printf(p, "     ");
+
+                       for (j = 0; j < len; j++)
+                               drm_printf(p, ascii85_encode(ptr[j], out));
+
+                       drm_printf(p, "\n");
+               }
        }
 
        drm_puts(p, "registers:\n");
index b1cb44922441db071da6166ca098846129a08831..878090b57e902967b63a9499362cff253487dfec 100644 (file)
@@ -191,6 +191,8 @@ struct msm_gpu_state {
                u32 seqno;
                u32 rptr;
                u32 wptr;
+               void *data;
+               int data_size;
        } ring[MSM_GPU_MAX_RINGS];
 
        int nr_registers;