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

Commit ce9c09a2 authored by Harshdeep Dhatt's avatar Harshdeep Dhatt Committed by Gerrit - the friendly Code Review server
Browse files

msm: kgsl: Get names of all fences



Sometimes, we may be given a fence array to wait on.
And fence array goes by a generic name, so it is hard
to tell to which driver the individual fences belong
to. Store names of all individual fences that are in
the fence array so that we can print them in case of
fence timeouts or tracepoints for better debugging.

Change-Id: I466606a5c10db11a5737fc1014185a9e72df5391
Signed-off-by: default avatarHarshdeep Dhatt <hdhatt@codeaurora.org>
Signed-off-by: default avatarRaghu Ananya Arabolu <rarabolu@codeaurora.org>
parent 5da70b20
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -130,8 +130,11 @@ static void sync_event_print(struct seq_file *s,
		break;
	}
	case KGSL_CMD_SYNCPOINT_TYPE_FENCE: {
		seq_printf(s, "sync: [%pK] %s", sync_event->handle,
				sync_event->fence_name);
		int i;

		for (i = 0; i < sync_event->info.num_fences; i++)
			seq_printf(s, "sync: %s",
				sync_event->info.fences[i].name);
		break;
	}
	default:
+1 −1
Original line number Diff line number Diff line
@@ -2064,7 +2064,7 @@ static long gpuobj_free_on_fence(struct kgsl_device_private *dev_priv,
	}

	handle = kgsl_sync_fence_async_wait(event.fd,
		gpuobj_free_fence_func, entry, NULL, 0);
		gpuobj_free_fence_func, entry, NULL);

	if (IS_ERR(handle)) {
		kgsl_mem_entry_unset_pend(entry);
+36 −10
Original line number Diff line number Diff line
@@ -36,6 +36,17 @@
static struct kmem_cache *memobjs_cache;
static struct kmem_cache *sparseobjs_cache;

static void free_fence_names(struct kgsl_drawobj_sync *syncobj)
{
	unsigned int i;

	for (i = 0; i < syncobj->numsyncs; i++) {
		struct kgsl_drawobj_sync_event *event = &syncobj->synclist[i];

		if (event->type == KGSL_CMD_SYNCPOINT_TYPE_FENCE)
			kfree(event->info.fences);
	}
}

void kgsl_drawobj_destroy_object(struct kref *kref)
{
@@ -48,6 +59,7 @@ void kgsl_drawobj_destroy_object(struct kref *kref)
	switch (drawobj->type) {
	case SYNCOBJ_TYPE:
		syncobj = SYNCOBJ(drawobj);
		free_fence_names(syncobj);
		kfree(syncobj->synclist);
		kfree(syncobj);
		break;
@@ -87,13 +99,18 @@ void kgsl_dump_syncpoints(struct kgsl_device *device,
				retired);
			break;
		}
		case KGSL_CMD_SYNCPOINT_TYPE_FENCE:
			dev_err(device->dev, "  fence: %s\n",
					event->fence_name);
		case KGSL_CMD_SYNCPOINT_TYPE_FENCE: {
			int j;
			struct event_fence_info *info = &event->info;

			for (j = 0; j < info->num_fences; j++)
				dev_err(device->dev, "[%d]  fence: %s\n",
					i, info->fences[j].name);
			break;
		}
		}
	}
}

static void syncobj_timer(struct timer_list *t)
{
@@ -139,12 +156,17 @@ static void syncobj_timer(struct timer_list *t)
			dev_err(device->dev, "       [%d] TIMESTAMP %d:%d\n",
				i, event->context->id, event->timestamp);
			break;
		case KGSL_CMD_SYNCPOINT_TYPE_FENCE:
		case KGSL_CMD_SYNCPOINT_TYPE_FENCE: {
			int j;
			struct event_fence_info *info = &event->info;

			for (j = 0; j < info->num_fences; j++)
				dev_err(device->dev, "       [%d] FENCE %s\n",
					i, event->fence_name);
					i, info->fences[j].name);
			break;
		}
		}
	}

	kgsl_drawobj_put(drawobj);
	dev_err(device->dev, "--gpu syncpoint deadlock print end--\n");
@@ -325,8 +347,11 @@ EXPORT_SYMBOL(kgsl_drawobj_destroy);
static bool drawobj_sync_fence_func(void *priv)
{
	struct kgsl_drawobj_sync_event *event = priv;
	int i;

	trace_syncpoint_fence_expire(event->syncobj, event->fence_name);
	for (i = 0; i < event->info.num_fences; i++)
		trace_syncpoint_fence_expire(event->syncobj,
			event->info.fences[i].name);

	/*
	 * Only call kgsl_drawobj_put() if it's not marked for cancellation
@@ -352,7 +377,7 @@ static int drawobj_add_sync_fence(struct kgsl_device *device,
	struct kgsl_cmd_syncpoint_fence *sync = priv;
	struct kgsl_drawobj *drawobj = DRAWOBJ(syncobj);
	struct kgsl_drawobj_sync_event *event;
	unsigned int id;
	unsigned int id, i;

	kref_get(&drawobj->refcount);

@@ -370,7 +395,7 @@ static int drawobj_add_sync_fence(struct kgsl_device *device,

	event->handle = kgsl_sync_fence_async_wait(sync->fd,
				drawobj_sync_fence_func, event,
				event->fence_name, sizeof(event->fence_name));
				&event->info);

	if (IS_ERR_OR_NULL(event->handle)) {
		int ret = PTR_ERR(event->handle);
@@ -390,7 +415,8 @@ static int drawobj_add_sync_fence(struct kgsl_device *device,
		return ret;
	}

	trace_syncpoint_fence(syncobj, event->fence_name);
	for (i = 0; i < event->info.num_fences; i++)
		trace_syncpoint_fence(syncobj, event->info.fences[i].name);

	return 0;
}
+12 −3
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
 * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
 */

#ifndef __KGSL_DRAWOBJ_H
@@ -100,6 +100,15 @@ struct kgsl_drawobj_sync {

#define KGSL_FENCE_NAME_LEN 74

struct fence_info {
	char name[KGSL_FENCE_NAME_LEN];
};

struct event_fence_info {
	struct fence_info *fences;
	int num_fences;
};

/**
 * struct kgsl_drawobj_sync_event
 * @id: identifer (positiion within the pending bitmap)
@@ -109,8 +118,8 @@ struct kgsl_drawobj_sync {
 *           register this event
 * @timestamp: Pending timestamp for the event
 * @handle: Pointer to a sync fence handle
 * @fence_name: A fence name string to describe the fence
 * @device: Pointer to the KGSL device
 * @info: structure to hold info about the fence
 */
struct kgsl_drawobj_sync_event {
	unsigned int id;
@@ -119,8 +128,8 @@ struct kgsl_drawobj_sync_event {
	struct kgsl_context *context;
	unsigned int timestamp;
	struct kgsl_sync_fence_cb *handle;
	char fence_name[KGSL_FENCE_NAME_LEN];
	struct kgsl_device *device;
	struct event_fence_info info;
};

/**
+40 −14
Original line number Diff line number Diff line
@@ -405,27 +405,54 @@ static void kgsl_sync_fence_callback(struct dma_fence *fence,
	}
}

static void kgsl_get_fence_name(struct dma_fence *fence,
	char *fence_name, int name_len)
static void kgsl_get_fence_names(struct dma_fence *fence,
	struct event_fence_info *info_ptr)
{
	char *ptr = fence_name;
	char *last = fence_name + name_len;
	unsigned int num_fences;
	struct dma_fence **fences;
	struct dma_fence_array *array;
	int i;

	ptr +=  scnprintf(ptr, last - ptr, "%s %s",
			fence->ops->get_driver_name(fence),
			fence->ops->get_timeline_name(fence));
	if (!info_ptr)
		return;

	array = to_dma_fence_array(fence);

	if (array != NULL) {
		num_fences = array->num_fences;
		fences = array->fences;
	} else {
		num_fences = 1;
		fences = &fence;
	}

	if ((ptr + 2) >= last)
	info_ptr->fences = kcalloc(num_fences, sizeof(struct fence_info),
			GFP_ATOMIC);
	if (info_ptr->fences == NULL)
		return;

	if (fence->ops->fence_value_str) {
		ptr += scnprintf(ptr, last - ptr, ": ");
		fence->ops->fence_value_str(fence, ptr, last - ptr);
	info_ptr->num_fences = num_fences;

	for (i = 0; i < num_fences; i++) {
		struct dma_fence *f = fences[i];
		struct fence_info *fi = &info_ptr->fences[i];
		int len;

		len =  scnprintf(fi->name, sizeof(fi->name), "%s %s",
			f->ops->get_driver_name(f),
			f->ops->get_timeline_name(f));

		if (f->ops->fence_value_str) {
			len += scnprintf(fi->name + len, sizeof(fi->name) - len,
				": ");
			f->ops->fence_value_str(f, fi->name + len,
				sizeof(fi->name) - len);
		}
	}
}

struct kgsl_sync_fence_cb *kgsl_sync_fence_async_wait(int fd,
	bool (*func)(void *priv), void *priv, char *fence_name, int name_len)
	bool (*func)(void *priv), void *priv, struct event_fence_info *info_ptr)
{
	struct kgsl_sync_fence_cb *kcb;
	struct dma_fence *fence;
@@ -446,8 +473,7 @@ struct kgsl_sync_fence_cb *kgsl_sync_fence_async_wait(int fd,
	kcb->priv = priv;
	kcb->func = func;

	if (fence_name)
		kgsl_get_fence_name(fence, fence_name, name_len);
	kgsl_get_fence_names(fence, info_ptr);

	/* if status then error or signaled */
	status = dma_fence_add_callback(fence, &kcb->fence_cb,
Loading