OSDN Git Service

msm: kgsl: Fix incomplete IB2 dump in the snapshot
authorHareesh Gundu <hareeshg@codeaurora.org>
Fri, 6 Jan 2017 10:07:09 +0000 (15:37 +0530)
committerGerrit - the friendly Code Review server <code-review@localhost>
Mon, 30 Jan 2017 11:29:07 +0000 (03:29 -0800)
If there is IB2 address overlap with IB object list,
driver is dumping pending dwords size of active IB2
data into snapshot. Fix this by updating IB2 size
while active IB1 parsing instead later point.

Change-Id: Ibb12a876ebf73846424232ef28e00d3dc9f9be59
Signed-off-by: Hareesh Gundu <hareeshg@codeaurora.org>
drivers/gpu/msm/adreno_cp_parser.c
drivers/gpu/msm/adreno_cp_parser.h
drivers/gpu/msm/adreno_snapshot.c
drivers/gpu/msm/kgsl_snapshot.h

index 2ccb813..d964537 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -53,7 +53,7 @@ static int load_state_unit_sizes[7][2] = {
 static int adreno_ib_find_objs(struct kgsl_device *device,
                                struct kgsl_process_private *process,
                                uint64_t gpuaddr, uint64_t dwords,
-                               int obj_type,
+                               uint64_t ib2base, int obj_type,
                                struct adreno_ib_object_list *ib_obj_list,
                                int ib_level);
 
@@ -483,7 +483,7 @@ static int ib_parse_draw_indx(struct kgsl_device *device, unsigned int *pkt,
                ret = adreno_ib_find_objs(device, process,
                        ib_parse_vars->set_draw_groups[i].cmd_stream_addr,
                        ib_parse_vars->set_draw_groups[i].cmd_stream_dwords,
-                       SNAPSHOT_GPU_OBJECT_DRAW,
+                       0, SNAPSHOT_GPU_OBJECT_DRAW,
                        ib_obj_list, 2);
                if (ret)
                        break;
@@ -686,8 +686,8 @@ static int ib_parse_type7_set_draw_state(struct kgsl_device *device,
                        if (cmd_stream_dwords)
                                ret = adreno_ib_find_objs(device, process,
                                        cmd_stream_addr, cmd_stream_dwords,
-                                       SNAPSHOT_GPU_OBJECT_DRAW, ib_obj_list,
-                                       2);
+                                       0, SNAPSHOT_GPU_OBJECT_DRAW,
+                                       ib_obj_list, 2);
                        if (ret)
                                break;
                        continue;
@@ -698,7 +698,7 @@ static int ib_parse_type7_set_draw_state(struct kgsl_device *device,
                        gpuaddr = gpuaddr << 32 | ptr[i + 1];
                        ret = adreno_ib_find_objs(device, process,
                                gpuaddr, (ptr[i] & 0x0000FFFF),
-                               SNAPSHOT_GPU_OBJECT_IB,
+                               0, SNAPSHOT_GPU_OBJECT_IB,
                                ib_obj_list, 2);
                        if (ret)
                                break;
@@ -760,7 +760,7 @@ static int ib_parse_set_draw_state(struct kgsl_device *device,
                if (flags & 0x8) {
                        ret = adreno_ib_find_objs(device, process,
                                ptr[i + 1], (ptr[i] & 0x0000FFFF),
-                               SNAPSHOT_GPU_OBJECT_IB,
+                               0, SNAPSHOT_GPU_OBJECT_IB,
                                ib_obj_list, 2);
                        if (ret)
                                break;
@@ -775,6 +775,7 @@ static int ib_parse_set_draw_state(struct kgsl_device *device,
  * @process: Process in which the IB is allocated
  * @gpuaddr: IB2 gpuaddr
  * @dwords: IB2 size in dwords
+ * @ib2base: Base address of active IB2
  * @ib_obj_list: List of objects found in IB
  * @ib_level: The level from which function is called, either from IB1 or IB2
  *
@@ -783,7 +784,7 @@ static int ib_parse_set_draw_state(struct kgsl_device *device,
  */
 static int adreno_cp_parse_ib2(struct kgsl_device *device,
                        struct kgsl_process_private *process,
-                       uint64_t gpuaddr, uint64_t dwords,
+                       uint64_t gpuaddr, uint64_t dwords, uint64_t ib2base,
                        struct adreno_ib_object_list *ib_obj_list,
                        int ib_level)
 {
@@ -794,6 +795,10 @@ static int adreno_cp_parse_ib2(struct kgsl_device *device,
         */
        if (2 == ib_level)
                return -EINVAL;
+
+       /* Save current IB2 statically */
+       if (ib2base == gpuaddr)
+               kgsl_snapshot_push_object(process, gpuaddr, dwords);
        /*
         * only try to find sub objects iff this IB has
         * not been processed already
@@ -807,7 +812,7 @@ static int adreno_cp_parse_ib2(struct kgsl_device *device,
                        return 0;
        }
 
-       return adreno_ib_find_objs(device, process, gpuaddr, dwords,
+       return adreno_ib_find_objs(device, process, gpuaddr, dwords, ib2base,
                SNAPSHOT_GPU_OBJECT_IB, ib_obj_list, 2);
 }
 
@@ -816,6 +821,7 @@ static int adreno_cp_parse_ib2(struct kgsl_device *device,
  * @device: The device pointer on which the IB executes
  * @process: The process in which the IB and all contained objects are mapped.
  * @gpuaddr: The gpu address of the IB
+ * @ib2base: IB2 base address
  * @dwords: Size of ib in dwords
  * @obj_type: The object type can be either an IB or a draw state sequence
  * @ib_obj_list: The list in which the IB and the objects in it are added.
@@ -828,7 +834,7 @@ static int adreno_cp_parse_ib2(struct kgsl_device *device,
 static int adreno_ib_find_objs(struct kgsl_device *device,
                                struct kgsl_process_private *process,
                                uint64_t gpuaddr, uint64_t dwords,
-                               int obj_type,
+                               uint64_t ib2base, int obj_type,
                                struct adreno_ib_object_list *ib_obj_list,
                                int ib_level)
 {
@@ -904,7 +910,7 @@ static int adreno_ib_find_objs(struct kgsl_device *device,
                                uint64_t size = src[i + 2];
 
                                ret = adreno_cp_parse_ib2(device, process,
-                                               gpuaddrib2, size,
+                                               gpuaddrib2, size, ib2base,
                                                ib_obj_list, ib_level);
                                if (ret)
                                        goto done;
@@ -930,7 +936,7 @@ static int adreno_ib_find_objs(struct kgsl_device *device,
                                gpuaddrib2 = gpuaddrib2 << 32 | src[i + 1];
 
                                ret = adreno_cp_parse_ib2(device, process,
-                                               gpuaddrib2, size,
+                                               gpuaddrib2, size, ib2base,
                                                ib_obj_list, ib_level);
                                if (ret)
                                        goto done;
@@ -982,6 +988,7 @@ done:
  * @process: The process in which the IB and all contained objects are mapped
  * @gpuaddr: The gpu address of the IB
  * @dwords: Size of ib in dwords
+ * @ib2base: Base address of active IB2
  * @ib_obj_list: The list in which the IB and the objects in it are added.
  *
  * Find all the memory objects that an IB needs for execution and place
@@ -993,7 +1000,7 @@ done:
  */
 int adreno_ib_create_object_list(struct kgsl_device *device,
                struct kgsl_process_private *process,
-               uint64_t gpuaddr, uint64_t dwords,
+               uint64_t gpuaddr, uint64_t dwords, uint64_t ib2base,
                struct adreno_ib_object_list **out_ib_obj_list)
 {
        int ret = 0;
@@ -1016,7 +1023,7 @@ int adreno_ib_create_object_list(struct kgsl_device *device,
                return -ENOMEM;
        }
 
-       ret = adreno_ib_find_objs(device, process, gpuaddr, dwords,
+       ret = adreno_ib_find_objs(device, process, gpuaddr, dwords, ib2base,
                SNAPSHOT_GPU_OBJECT_IB, ib_obj_list, 1);
 
        /* Even if there was an error return the remaining objects found */
index 0248de2..f4d6cd9 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014,2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -178,7 +178,7 @@ static inline int adreno_cp_parser_regindex(struct adreno_device *adreno_dev,
 int adreno_ib_create_object_list(
                struct kgsl_device *device,
                struct kgsl_process_private *process,
-               uint64_t gpuaddr, uint64_t dwords,
+               uint64_t gpuaddr, uint64_t dwords, uint64_t ib2base,
                struct adreno_ib_object_list **out_ib_obj_list);
 
 void adreno_ib_destroy_obj_list(struct adreno_ib_object_list *ib_obj_list);
index 08d7d3c..711d7ba 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -27,8 +27,6 @@
 
 #define SNAPSHOT_OBJ_BUFSIZE 64
 
-#define SNAPSHOT_OBJ_TYPE_IB 0
-
 /* Used to print error message if an IB has too many objects in it */
 static int ib_max_objs;
 
@@ -53,8 +51,7 @@ static inline int adreno_rb_ctxtswitch(struct adreno_device *adreno_dev,
 }
 
 /* Push a new buffer object onto the list */
-static void push_object(int type,
-       struct kgsl_process_private *process,
+void kgsl_snapshot_push_object(struct kgsl_process_private *process,
        uint64_t gpuaddr, uint64_t dwords)
 {
        int index;
@@ -101,7 +98,6 @@ static void push_object(int type,
        }
 
        /* Put it on the list of things to parse */
-       objbuf[objbufptr].type = type;
        objbuf[objbufptr].gpuaddr = gpuaddr;
        objbuf[objbufptr].size = dwords << 2;
        objbuf[objbufptr++].entry = entry;
@@ -112,8 +108,7 @@ static void push_object(int type,
  * to be dumped
  */
 
-static int find_object(int type, uint64_t gpuaddr,
-               struct kgsl_process_private *process)
+static int find_object(uint64_t gpuaddr, struct kgsl_process_private *process)
 {
        int index;
 
@@ -131,14 +126,12 @@ static int find_object(int type, uint64_t gpuaddr,
  * @snapshot: The snapshot data.
  * @process: The process to which the IB belongs
  * @ib_obj_list: List of the IB objects
- * @ib2base: IB2 base address at time of the fault
  *
  * Returns 0 on success else error code
  */
 static int snapshot_freeze_obj_list(struct kgsl_snapshot *snapshot,
                struct kgsl_process_private *process,
-               struct adreno_ib_object_list *ib_obj_list,
-               uint64_t ib2base)
+               struct adreno_ib_object_list *ib_obj_list)
 {
        int ret = 0;
        struct adreno_ib_object *ib_objs;
@@ -163,21 +156,15 @@ static int snapshot_freeze_obj_list(struct kgsl_snapshot *snapshot,
                }
 
                if (freeze) {
-                       /* Save current IB2 statically */
-                       if (ib2base == ib_objs->gpuaddr) {
-                               push_object(SNAPSHOT_OBJ_TYPE_IB,
-                               process, ib_objs->gpuaddr, ib_objs->size >> 2);
+                       temp_ret = kgsl_snapshot_get_object(snapshot,
+                                           process, ib_objs->gpuaddr,
+                                           ib_objs->size,
+                                           ib_objs->snapshot_obj_type);
+                       if (temp_ret < 0) {
+                               if (ret >= 0)
+                                       ret = temp_ret;
                        } else {
-                               temp_ret = kgsl_snapshot_get_object(snapshot,
-                                       process, ib_objs->gpuaddr,
-                                       ib_objs->size,
-                                       ib_objs->snapshot_obj_type);
-                               if (temp_ret < 0) {
-                                       if (ret >= 0)
-                                               ret = temp_ret;
-                               } else {
-                                       snapshot_frozen_objsize += temp_ret;
-                               }
+                               snapshot_frozen_objsize += temp_ret;
                        }
                }
        }
@@ -203,8 +190,7 @@ static inline void parse_ib(struct kgsl_device *device,
         * list
         */
        if (gpuaddr == snapshot->ib1base) {
-               push_object(SNAPSHOT_OBJ_TYPE_IB, process,
-                       gpuaddr, dwords);
+               kgsl_snapshot_push_object(process, gpuaddr, dwords);
                return;
        }
 
@@ -213,7 +199,8 @@ static inline void parse_ib(struct kgsl_device *device,
                return;
 
        if (-E2BIG == adreno_ib_create_object_list(device, process,
-                               gpuaddr, dwords, &ib_obj_list))
+                               gpuaddr, dwords, snapshot->ib2base,
+                               &ib_obj_list))
                ib_max_objs = 1;
 
        if (ib_obj_list)
@@ -559,8 +546,7 @@ void kgsl_snapshot_add_active_ib_obj_list(struct kgsl_device *device,
        int index = -ENOENT;
 
        if (!snapshot->ib1dumped)
-               index = find_object(SNAPSHOT_OBJ_TYPE_IB, snapshot->ib1base,
-                               snapshot->process);
+               index = find_object(snapshot->ib1base, snapshot->process);
 
        /* only do this for IB1 because the IB2's are part of IB1 objects */
        if ((index != -ENOENT) &&
@@ -569,19 +555,19 @@ void kgsl_snapshot_add_active_ib_obj_list(struct kgsl_device *device,
                                        objbuf[index].entry->priv,
                                        objbuf[index].gpuaddr,
                                        objbuf[index].size >> 2,
+                                       snapshot->ib2base,
                                        &ib_obj_list))
                        ib_max_objs = 1;
                if (ib_obj_list) {
                        /* freeze the IB objects in the IB */
                        snapshot_freeze_obj_list(snapshot,
                                        objbuf[index].entry->priv,
-                                       ib_obj_list, snapshot->ib2base);
+                                       ib_obj_list);
                        adreno_ib_destroy_obj_list(ib_obj_list);
                }
        } else {
                /* Get the IB2 index from parsed object */
-               index = find_object(SNAPSHOT_OBJ_TYPE_IB, snapshot->ib2base,
-                               snapshot->process);
+               index = find_object(snapshot->ib2base, snapshot->process);
 
                if (index != -ENOENT)
                        parse_ib(device, snapshot, snapshot->process,
@@ -624,6 +610,7 @@ static size_t snapshot_ib(struct kgsl_device *device, u8 *buf,
        struct adreno_ib_object_list *ib_obj_list;
        struct kgsl_snapshot *snapshot;
        struct kgsl_snapshot_object *obj;
+       struct kgsl_memdesc *memdesc;
 
        if (meta == NULL || meta->snapshot == NULL || meta->obj == NULL) {
                KGSL_CORE_ERR("snapshot: bad metadata");
@@ -631,13 +618,18 @@ static size_t snapshot_ib(struct kgsl_device *device, u8 *buf,
        }
        snapshot = meta->snapshot;
        obj = meta->obj;
+       memdesc = &obj->entry->memdesc;
+
+       /* If size is zero get it from the medesc size */
+       if (!obj->size)
+               obj->size = (memdesc->size - (obj->gpuaddr - memdesc->gpuaddr));
 
        if (remain < (obj->size + sizeof(*header))) {
                KGSL_CORE_ERR("snapshot: Not enough memory for the ib\n");
                return 0;
        }
 
-       src = kgsl_gpuaddr_to_vaddr(&obj->entry->memdesc, obj->gpuaddr);
+       src = kgsl_gpuaddr_to_vaddr(memdesc, obj->gpuaddr);
        if (src == NULL) {
                KGSL_DRV_ERR(device,
                        "snapshot: Unable to map GPU memory object 0x%016llX into the kernel\n",
@@ -653,13 +645,14 @@ static size_t snapshot_ib(struct kgsl_device *device, u8 *buf,
                if (-E2BIG == adreno_ib_create_object_list(device,
                                obj->entry->priv,
                                obj->gpuaddr, obj->size >> 2,
+                               snapshot->ib2base,
                                &ib_obj_list))
                        ib_max_objs = 1;
                if (ib_obj_list) {
                        /* freeze the IB objects in the IB */
                        snapshot_freeze_obj_list(snapshot,
                                                obj->entry->priv,
-                                               ib_obj_list, meta->ib2base);
+                                               ib_obj_list);
                        adreno_ib_destroy_obj_list(ib_obj_list);
                }
        }
@@ -688,26 +681,18 @@ static void dump_object(struct kgsl_device *device, int obj,
 {
        struct snapshot_ib_meta meta;
 
-       switch (objbuf[obj].type) {
-       case SNAPSHOT_OBJ_TYPE_IB:
-               meta.snapshot = snapshot;
-               meta.obj = &objbuf[obj];
-               meta.ib1base = snapshot->ib1base;
-               meta.ib1size = snapshot->ib1size;
-               meta.ib2base = snapshot->ib2base;
-               meta.ib2size = snapshot->ib2size;
+       meta.snapshot = snapshot;
+       meta.obj = &objbuf[obj];
+       meta.ib1base = snapshot->ib1base;
+       meta.ib1size = snapshot->ib1size;
+       meta.ib2base = snapshot->ib2base;
+       meta.ib2size = snapshot->ib2size;
 
-               kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_IB_V2,
+       kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_IB_V2,
                        snapshot, snapshot_ib, &meta);
-               if (objbuf[obj].entry) {
-                       kgsl_memdesc_unmap(&(objbuf[obj].entry->memdesc));
-                       kgsl_mem_entry_put(objbuf[obj].entry);
-               }
-               break;
-       default:
-               KGSL_CORE_ERR("snapshot: Invalid snapshot object type: %d\n",
-                       objbuf[obj].type);
-               break;
+       if (objbuf[obj].entry) {
+               kgsl_memdesc_unmap(&(objbuf[obj].entry->memdesc));
+               kgsl_mem_entry_put(objbuf[obj].entry);
        }
 }
 
@@ -909,10 +894,10 @@ void adreno_snapshot(struct kgsl_device *device, struct kgsl_snapshot *snapshot,
         * figure how often this really happens.
         */
 
-       if (-ENOENT == find_object(SNAPSHOT_OBJ_TYPE_IB, snapshot->ib1base,
-                       snapshot->process) && snapshot->ib1size) {
-               push_object(SNAPSHOT_OBJ_TYPE_IB, snapshot->process,
-                       snapshot->ib1base, snapshot->ib1size);
+       if (-ENOENT == find_object(snapshot->ib1base, snapshot->process) &&
+                       snapshot->ib1size) {
+               kgsl_snapshot_push_object(snapshot->process, snapshot->ib1base,
+                               snapshot->ib1size);
                KGSL_CORE_ERR(
                "CP_IB1_BASE not found in the ringbuffer.Dumping %x dwords of the buffer.\n",
                snapshot->ib1size);
@@ -926,10 +911,9 @@ void adreno_snapshot(struct kgsl_device *device, struct kgsl_snapshot *snapshot,
         * correct size.
         */
 
-       if (-ENOENT == find_object(SNAPSHOT_OBJ_TYPE_IB, snapshot->ib2base,
-               snapshot->process)) {
-               push_object(SNAPSHOT_OBJ_TYPE_IB, snapshot->process,
-                       snapshot->ib2base, snapshot->ib2size);
+       if (-ENOENT == find_object(snapshot->ib2base, snapshot->process)) {
+               kgsl_snapshot_push_object(snapshot->process, snapshot->ib2base,
+                               snapshot->ib2size);
        }
 
        /*
index e2ded87..2cb8b8f 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -255,4 +255,6 @@ struct kgsl_snapshot_gpu_object_v2 {
        __u64 size;    /* Size of the object (in dwords) */
 } __packed;
 
+void kgsl_snapshot_push_object(struct kgsl_process_private *process,
+       uint64_t gpuaddr, uint64_t dwords);
 #endif