Merge "msm: kgsl: Fix incomplete IB2 dump in the snapshot"

This commit is contained in:
Linux Build Service Account 2017-01-30 07:05:35 -08:00 committed by Gerrit - the friendly Code Review server
commit f9500f4705
4 changed files with 71 additions and 78 deletions

View 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 * 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 * 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, static int adreno_ib_find_objs(struct kgsl_device *device,
struct kgsl_process_private *process, struct kgsl_process_private *process,
uint64_t gpuaddr, uint64_t dwords, uint64_t gpuaddr, uint64_t dwords,
int obj_type, uint64_t ib2base, int obj_type,
struct adreno_ib_object_list *ib_obj_list, struct adreno_ib_object_list *ib_obj_list,
int ib_level); 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, 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_addr,
ib_parse_vars->set_draw_groups[i].cmd_stream_dwords, ib_parse_vars->set_draw_groups[i].cmd_stream_dwords,
SNAPSHOT_GPU_OBJECT_DRAW, 0, SNAPSHOT_GPU_OBJECT_DRAW,
ib_obj_list, 2); ib_obj_list, 2);
if (ret) if (ret)
break; break;
@ -686,8 +686,8 @@ static int ib_parse_type7_set_draw_state(struct kgsl_device *device,
if (cmd_stream_dwords) if (cmd_stream_dwords)
ret = adreno_ib_find_objs(device, process, ret = adreno_ib_find_objs(device, process,
cmd_stream_addr, cmd_stream_dwords, cmd_stream_addr, cmd_stream_dwords,
SNAPSHOT_GPU_OBJECT_DRAW, ib_obj_list, 0, SNAPSHOT_GPU_OBJECT_DRAW,
2); ib_obj_list, 2);
if (ret) if (ret)
break; break;
continue; continue;
@ -698,7 +698,7 @@ static int ib_parse_type7_set_draw_state(struct kgsl_device *device,
gpuaddr = gpuaddr << 32 | ptr[i + 1]; gpuaddr = gpuaddr << 32 | ptr[i + 1];
ret = adreno_ib_find_objs(device, process, ret = adreno_ib_find_objs(device, process,
gpuaddr, (ptr[i] & 0x0000FFFF), gpuaddr, (ptr[i] & 0x0000FFFF),
SNAPSHOT_GPU_OBJECT_IB, 0, SNAPSHOT_GPU_OBJECT_IB,
ib_obj_list, 2); ib_obj_list, 2);
if (ret) if (ret)
break; break;
@ -760,7 +760,7 @@ static int ib_parse_set_draw_state(struct kgsl_device *device,
if (flags & 0x8) { if (flags & 0x8) {
ret = adreno_ib_find_objs(device, process, ret = adreno_ib_find_objs(device, process,
ptr[i + 1], (ptr[i] & 0x0000FFFF), ptr[i + 1], (ptr[i] & 0x0000FFFF),
SNAPSHOT_GPU_OBJECT_IB, 0, SNAPSHOT_GPU_OBJECT_IB,
ib_obj_list, 2); ib_obj_list, 2);
if (ret) if (ret)
break; break;
@ -775,6 +775,7 @@ static int ib_parse_set_draw_state(struct kgsl_device *device,
* @process: Process in which the IB is allocated * @process: Process in which the IB is allocated
* @gpuaddr: IB2 gpuaddr * @gpuaddr: IB2 gpuaddr
* @dwords: IB2 size in dwords * @dwords: IB2 size in dwords
* @ib2base: Base address of active IB2
* @ib_obj_list: List of objects found in IB * @ib_obj_list: List of objects found in IB
* @ib_level: The level from which function is called, either from IB1 or IB2 * @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, static int adreno_cp_parse_ib2(struct kgsl_device *device,
struct kgsl_process_private *process, 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, struct adreno_ib_object_list *ib_obj_list,
int ib_level) int ib_level)
{ {
@ -794,6 +795,10 @@ static int adreno_cp_parse_ib2(struct kgsl_device *device,
*/ */
if (2 == ib_level) if (2 == ib_level)
return -EINVAL; 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 * only try to find sub objects iff this IB has
* not been processed already * not been processed already
@ -807,7 +812,7 @@ static int adreno_cp_parse_ib2(struct kgsl_device *device,
return 0; 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); 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 * @device: The device pointer on which the IB executes
* @process: The process in which the IB and all contained objects are mapped. * @process: The process in which the IB and all contained objects are mapped.
* @gpuaddr: The gpu address of the IB * @gpuaddr: The gpu address of the IB
* @ib2base: IB2 base address
* @dwords: Size of ib in dwords * @dwords: Size of ib in dwords
* @obj_type: The object type can be either an IB or a draw state sequence * @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. * @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, static int adreno_ib_find_objs(struct kgsl_device *device,
struct kgsl_process_private *process, struct kgsl_process_private *process,
uint64_t gpuaddr, uint64_t dwords, uint64_t gpuaddr, uint64_t dwords,
int obj_type, uint64_t ib2base, int obj_type,
struct adreno_ib_object_list *ib_obj_list, struct adreno_ib_object_list *ib_obj_list,
int ib_level) int ib_level)
{ {
@ -904,7 +910,7 @@ static int adreno_ib_find_objs(struct kgsl_device *device,
uint64_t size = src[i + 2]; uint64_t size = src[i + 2];
ret = adreno_cp_parse_ib2(device, process, ret = adreno_cp_parse_ib2(device, process,
gpuaddrib2, size, gpuaddrib2, size, ib2base,
ib_obj_list, ib_level); ib_obj_list, ib_level);
if (ret) if (ret)
goto done; goto done;
@ -930,7 +936,7 @@ static int adreno_ib_find_objs(struct kgsl_device *device,
gpuaddrib2 = gpuaddrib2 << 32 | src[i + 1]; gpuaddrib2 = gpuaddrib2 << 32 | src[i + 1];
ret = adreno_cp_parse_ib2(device, process, ret = adreno_cp_parse_ib2(device, process,
gpuaddrib2, size, gpuaddrib2, size, ib2base,
ib_obj_list, ib_level); ib_obj_list, ib_level);
if (ret) if (ret)
goto done; goto done;
@ -982,6 +988,7 @@ done:
* @process: The process in which the IB and all contained objects are mapped * @process: The process in which the IB and all contained objects are mapped
* @gpuaddr: The gpu address of the IB * @gpuaddr: The gpu address of the IB
* @dwords: Size of ib in dwords * @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. * @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 * 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, int adreno_ib_create_object_list(struct kgsl_device *device,
struct kgsl_process_private *process, 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) struct adreno_ib_object_list **out_ib_obj_list)
{ {
int ret = 0; int ret = 0;
@ -1016,7 +1023,7 @@ int adreno_ib_create_object_list(struct kgsl_device *device,
return -ENOMEM; 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); SNAPSHOT_GPU_OBJECT_IB, ib_obj_list, 1);
/* Even if there was an error return the remaining objects found */ /* Even if there was an error return the remaining objects found */

View 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 * 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 * 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( int adreno_ib_create_object_list(
struct kgsl_device *device, struct kgsl_device *device,
struct kgsl_process_private *process, 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); struct adreno_ib_object_list **out_ib_obj_list);
void adreno_ib_destroy_obj_list(struct adreno_ib_object_list *ib_obj_list); void adreno_ib_destroy_obj_list(struct adreno_ib_object_list *ib_obj_list);

View 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 * 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 * 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_BUFSIZE 64
#define SNAPSHOT_OBJ_TYPE_IB 0
/* Used to print error message if an IB has too many objects in it */ /* Used to print error message if an IB has too many objects in it */
static int ib_max_objs; 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 */ /* Push a new buffer object onto the list */
static void push_object(int type, void kgsl_snapshot_push_object(struct kgsl_process_private *process,
struct kgsl_process_private *process,
uint64_t gpuaddr, uint64_t dwords) uint64_t gpuaddr, uint64_t dwords)
{ {
int index; int index;
@ -101,7 +98,6 @@ static void push_object(int type,
} }
/* Put it on the list of things to parse */ /* Put it on the list of things to parse */
objbuf[objbufptr].type = type;
objbuf[objbufptr].gpuaddr = gpuaddr; objbuf[objbufptr].gpuaddr = gpuaddr;
objbuf[objbufptr].size = dwords << 2; objbuf[objbufptr].size = dwords << 2;
objbuf[objbufptr++].entry = entry; objbuf[objbufptr++].entry = entry;
@ -112,8 +108,7 @@ static void push_object(int type,
* to be dumped * to be dumped
*/ */
static int find_object(int type, uint64_t gpuaddr, static int find_object(uint64_t gpuaddr, struct kgsl_process_private *process)
struct kgsl_process_private *process)
{ {
int index; int index;
@ -131,14 +126,12 @@ static int find_object(int type, uint64_t gpuaddr,
* @snapshot: The snapshot data. * @snapshot: The snapshot data.
* @process: The process to which the IB belongs * @process: The process to which the IB belongs
* @ib_obj_list: List of the IB objects * @ib_obj_list: List of the IB objects
* @ib2base: IB2 base address at time of the fault
* *
* Returns 0 on success else error code * Returns 0 on success else error code
*/ */
static int snapshot_freeze_obj_list(struct kgsl_snapshot *snapshot, static int snapshot_freeze_obj_list(struct kgsl_snapshot *snapshot,
struct kgsl_process_private *process, struct kgsl_process_private *process,
struct adreno_ib_object_list *ib_obj_list, struct adreno_ib_object_list *ib_obj_list)
uint64_t ib2base)
{ {
int ret = 0; int ret = 0;
struct adreno_ib_object *ib_objs; struct adreno_ib_object *ib_objs;
@ -163,21 +156,15 @@ static int snapshot_freeze_obj_list(struct kgsl_snapshot *snapshot,
} }
if (freeze) { if (freeze) {
/* Save current IB2 statically */ temp_ret = kgsl_snapshot_get_object(snapshot,
if (ib2base == ib_objs->gpuaddr) { process, ib_objs->gpuaddr,
push_object(SNAPSHOT_OBJ_TYPE_IB, ib_objs->size,
process, ib_objs->gpuaddr, ib_objs->size >> 2); ib_objs->snapshot_obj_type);
if (temp_ret < 0) {
if (ret >= 0)
ret = temp_ret;
} else { } else {
temp_ret = kgsl_snapshot_get_object(snapshot, snapshot_frozen_objsize += temp_ret;
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;
}
} }
} }
} }
@ -203,8 +190,7 @@ static inline void parse_ib(struct kgsl_device *device,
* list * list
*/ */
if (gpuaddr == snapshot->ib1base) { if (gpuaddr == snapshot->ib1base) {
push_object(SNAPSHOT_OBJ_TYPE_IB, process, kgsl_snapshot_push_object(process, gpuaddr, dwords);
gpuaddr, dwords);
return; return;
} }
@ -213,7 +199,8 @@ static inline void parse_ib(struct kgsl_device *device,
return; return;
if (-E2BIG == adreno_ib_create_object_list(device, process, 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; ib_max_objs = 1;
if (ib_obj_list) if (ib_obj_list)
@ -559,8 +546,7 @@ void kgsl_snapshot_add_active_ib_obj_list(struct kgsl_device *device,
int index = -ENOENT; int index = -ENOENT;
if (!snapshot->ib1dumped) if (!snapshot->ib1dumped)
index = find_object(SNAPSHOT_OBJ_TYPE_IB, snapshot->ib1base, index = find_object(snapshot->ib1base, snapshot->process);
snapshot->process);
/* only do this for IB1 because the IB2's are part of IB1 objects */ /* only do this for IB1 because the IB2's are part of IB1 objects */
if ((index != -ENOENT) && 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].entry->priv,
objbuf[index].gpuaddr, objbuf[index].gpuaddr,
objbuf[index].size >> 2, objbuf[index].size >> 2,
snapshot->ib2base,
&ib_obj_list)) &ib_obj_list))
ib_max_objs = 1; ib_max_objs = 1;
if (ib_obj_list) { if (ib_obj_list) {
/* freeze the IB objects in the IB */ /* freeze the IB objects in the IB */
snapshot_freeze_obj_list(snapshot, snapshot_freeze_obj_list(snapshot,
objbuf[index].entry->priv, objbuf[index].entry->priv,
ib_obj_list, snapshot->ib2base); ib_obj_list);
adreno_ib_destroy_obj_list(ib_obj_list); adreno_ib_destroy_obj_list(ib_obj_list);
} }
} else { } else {
/* Get the IB2 index from parsed object */ /* Get the IB2 index from parsed object */
index = find_object(SNAPSHOT_OBJ_TYPE_IB, snapshot->ib2base, index = find_object(snapshot->ib2base, snapshot->process);
snapshot->process);
if (index != -ENOENT) if (index != -ENOENT)
parse_ib(device, snapshot, snapshot->process, 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 adreno_ib_object_list *ib_obj_list;
struct kgsl_snapshot *snapshot; struct kgsl_snapshot *snapshot;
struct kgsl_snapshot_object *obj; struct kgsl_snapshot_object *obj;
struct kgsl_memdesc *memdesc;
if (meta == NULL || meta->snapshot == NULL || meta->obj == NULL) { if (meta == NULL || meta->snapshot == NULL || meta->obj == NULL) {
KGSL_CORE_ERR("snapshot: bad metadata"); KGSL_CORE_ERR("snapshot: bad metadata");
@ -631,13 +618,18 @@ static size_t snapshot_ib(struct kgsl_device *device, u8 *buf,
} }
snapshot = meta->snapshot; snapshot = meta->snapshot;
obj = meta->obj; 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))) { if (remain < (obj->size + sizeof(*header))) {
KGSL_CORE_ERR("snapshot: Not enough memory for the ib\n"); KGSL_CORE_ERR("snapshot: Not enough memory for the ib\n");
return 0; return 0;
} }
src = kgsl_gpuaddr_to_vaddr(&obj->entry->memdesc, obj->gpuaddr); src = kgsl_gpuaddr_to_vaddr(memdesc, obj->gpuaddr);
if (src == NULL) { if (src == NULL) {
KGSL_DRV_ERR(device, KGSL_DRV_ERR(device,
"snapshot: Unable to map GPU memory object 0x%016llX into the kernel\n", "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, if (-E2BIG == adreno_ib_create_object_list(device,
obj->entry->priv, obj->entry->priv,
obj->gpuaddr, obj->size >> 2, obj->gpuaddr, obj->size >> 2,
snapshot->ib2base,
&ib_obj_list)) &ib_obj_list))
ib_max_objs = 1; ib_max_objs = 1;
if (ib_obj_list) { if (ib_obj_list) {
/* freeze the IB objects in the IB */ /* freeze the IB objects in the IB */
snapshot_freeze_obj_list(snapshot, snapshot_freeze_obj_list(snapshot,
obj->entry->priv, obj->entry->priv,
ib_obj_list, meta->ib2base); ib_obj_list);
adreno_ib_destroy_obj_list(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; struct snapshot_ib_meta meta;
switch (objbuf[obj].type) { meta.snapshot = snapshot;
case SNAPSHOT_OBJ_TYPE_IB: meta.obj = &objbuf[obj];
meta.snapshot = snapshot; meta.ib1base = snapshot->ib1base;
meta.obj = &objbuf[obj]; meta.ib1size = snapshot->ib1size;
meta.ib1base = snapshot->ib1base; meta.ib2base = snapshot->ib2base;
meta.ib1size = snapshot->ib1size; meta.ib2size = snapshot->ib2size;
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); snapshot, snapshot_ib, &meta);
if (objbuf[obj].entry) { if (objbuf[obj].entry) {
kgsl_memdesc_unmap(&(objbuf[obj].entry->memdesc)); kgsl_memdesc_unmap(&(objbuf[obj].entry->memdesc));
kgsl_mem_entry_put(objbuf[obj].entry); kgsl_mem_entry_put(objbuf[obj].entry);
}
break;
default:
KGSL_CORE_ERR("snapshot: Invalid snapshot object type: %d\n",
objbuf[obj].type);
break;
} }
} }
@ -909,10 +894,10 @@ void adreno_snapshot(struct kgsl_device *device, struct kgsl_snapshot *snapshot,
* figure how often this really happens. * figure how often this really happens.
*/ */
if (-ENOENT == find_object(SNAPSHOT_OBJ_TYPE_IB, snapshot->ib1base, if (-ENOENT == find_object(snapshot->ib1base, snapshot->process) &&
snapshot->process) && snapshot->ib1size) { snapshot->ib1size) {
push_object(SNAPSHOT_OBJ_TYPE_IB, snapshot->process, kgsl_snapshot_push_object(snapshot->process, snapshot->ib1base,
snapshot->ib1base, snapshot->ib1size); snapshot->ib1size);
KGSL_CORE_ERR( KGSL_CORE_ERR(
"CP_IB1_BASE not found in the ringbuffer.Dumping %x dwords of the buffer.\n", "CP_IB1_BASE not found in the ringbuffer.Dumping %x dwords of the buffer.\n",
snapshot->ib1size); snapshot->ib1size);
@ -926,10 +911,9 @@ void adreno_snapshot(struct kgsl_device *device, struct kgsl_snapshot *snapshot,
* correct size. * correct size.
*/ */
if (-ENOENT == find_object(SNAPSHOT_OBJ_TYPE_IB, snapshot->ib2base, if (-ENOENT == find_object(snapshot->ib2base, snapshot->process)) {
snapshot->process)) { kgsl_snapshot_push_object(snapshot->process, snapshot->ib2base,
push_object(SNAPSHOT_OBJ_TYPE_IB, snapshot->process, snapshot->ib2size);
snapshot->ib2base, snapshot->ib2size);
} }
/* /*

View 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 * 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 * 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) */ __u64 size; /* Size of the object (in dwords) */
} __packed; } __packed;
void kgsl_snapshot_push_object(struct kgsl_process_private *process,
uint64_t gpuaddr, uint64_t dwords);
#endif #endif