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 <jcro...@codeaurora.org>
---
 Documentation/gpu/drm-msm-crash-dump.txt |  5 ++++
 drivers/gpu/drm/msm/adreno/adreno_gpu.c  | 40 ++++++++++++++++++++++++++++++++
 drivers/gpu/drm/msm/msm_gpu.h            |  2 ++
 3 files changed, 47 insertions(+)

diff --git a/Documentation/gpu/drm-msm-crash-dump.txt 
b/Documentation/gpu/drm-msm-crash-dump.txt
index ec56640..3f54b44 100644
--- a/Documentation/gpu/drm-msm-crash-dump.txt
+++ b/Documentation/gpu/drm-msm-crash-dump.txt
@@ -22,6 +22,11 @@ ringbuffer:   # Ringbuffer data. There will be a sequence 
for each ringbuffer
    retired-fence:  # [decimal] THe last fence retired on the ring
    rptr:           # [decimal] The current read pointer (rptr) for the ring
    wptr:           # [decimal] The current write pointer (wptr) for the ring
+   size:           # [decimal] The maximum size of the ring programmed in the
+                   # hardware
+   data:           # [ascii85] The contents of the ring encoded as ascii85.
+                  # Only the unused portions of the ring will be printed (up
+                   # to a maximum of 'size' bytes
 registers:    # Sets of register values. This section can be used multiple
               # times for different ranges of registers. Each register will be
               # on its own line.
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c 
b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 920db2e..e9b7b36 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -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"
@@ -397,10 +398,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].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]);
+
+               /*
+                * Only copy used parts of the ring buffers (this should save
+                * data size for lightly used rings)
+                */
+               for(j = 0; j < MSM_GPU_RINGBUFFER_SZ >> 2; j++)
+                       if (gpu->rb[i]->start[j])
+                               size = j;
+
+               if (size) {
+                       state->ring[i].data = kmalloc((size + 1) << 2, 
GFP_KERNEL);
+                       if (state->ring[i].data) {
+                               memcpy(state->ring[i].data, gpu->rb[i]->start,
+                               (size + 1) << 2);
+                               state->ring[i].data_size = (size + 1) << 2;
+                       }
+               }
        }
 
        /* Count the number of registers */
@@ -431,9 +451,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);
@@ -473,6 +497,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_printf(p, "registers:\n");
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index e65f507..48f7b21 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -190,6 +190,8 @@ struct msm_gpu_state {
                u32 seqno;
                u32 rptr;
                u32 wptr;
+               void *data;
+               int data_size;
        } ring[MSM_GPU_MAX_RINGS];
 
        int nr_registers;
-- 
1.9.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to