Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a0c589a5 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

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

parents cd6f27b2 54732b2f
Loading
Loading
Loading
Loading
+21 −14
Original line number Diff line number Diff line
/* 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 */
+2 −2
Original line number Diff line number Diff line
/* 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);
+45 −61
Original line number Diff line number Diff line
/* 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,11 +156,6 @@ 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);
			} else {
			temp_ret = kgsl_snapshot_get_object(snapshot,
					    process, ib_objs->gpuaddr,
					    ib_objs->size,
@@ -180,7 +168,6 @@ static int snapshot_freeze_obj_list(struct kgsl_snapshot *snapshot,
			}
		}
	}
	}
	return 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,8 +681,6 @@ 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;
@@ -703,12 +694,6 @@ static void dump_object(struct kgsl_device *device, int obj,
		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;
	}
}

/* setup_fault process - Find kgsl_process_private struct that caused the fault
@@ -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);
	}

	/*
+3 −1
Original line number Diff line number Diff line
/* 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