From 0ebbdcdc1fa10b8ca31feac93fae237cfa0eb8c5 Mon Sep 17 00:00:00 2001 From: Puranam V G Tejaswi Date: Thu, 13 Dec 2018 15:47:00 +0530 Subject: [PATCH] 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: Harshdeep Dhatt Signed-off-by: Puranam V G Tejaswi --- drivers/gpu/msm/adreno_debugfs.c | 9 +++-- drivers/gpu/msm/kgsl.c | 2 +- drivers/gpu/msm/kgsl_drawobj.c | 48 ++++++++++++++++++++------- drivers/gpu/msm/kgsl_drawobj.h | 15 +++++++-- drivers/gpu/msm/kgsl_sync.c | 56 +++++++++++++++++++++++--------- drivers/gpu/msm/kgsl_sync.h | 5 +-- 6 files changed, 100 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c index 2a1d352a2f51..aef802cbf491 100644 --- a/drivers/gpu/msm/adreno_debugfs.c +++ b/drivers/gpu/msm/adreno_debugfs.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2002,2008-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2002,2008-2018, 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 @@ -137,8 +137,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: diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index eb4c29d535d5..aba9ed07a41f 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -2018,7 +2018,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); diff --git a/drivers/gpu/msm/kgsl_drawobj.c b/drivers/gpu/msm/kgsl_drawobj.c index 3dbaea4a0ccb..a1e0f4c0d29b 100644 --- a/drivers/gpu/msm/kgsl_drawobj.c +++ b/drivers/gpu/msm/kgsl_drawobj.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2018, 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 @@ -43,6 +43,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) { @@ -55,6 +66,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; @@ -94,11 +106,16 @@ 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; } + } } } @@ -146,11 +163,16 @@ static void syncobj_timer(unsigned long data) dev_err(device->dev, " [%d] TIMESTAMP %d:%d\n", i, event->context->id, event->timestamp); break; - case KGSL_CMD_SYNCPOINT_TYPE_FENCE: - dev_err(device->dev, " [%d] FENCE %s\n", - i, 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; } + } } kgsl_drawobj_put(drawobj); @@ -332,8 +354,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 @@ -359,7 +384,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); @@ -377,7 +402,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); @@ -397,7 +422,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; } diff --git a/drivers/gpu/msm/kgsl_drawobj.h b/drivers/gpu/msm/kgsl_drawobj.h index 06eef7fdd884..bd32f5e503a7 100644 --- a/drivers/gpu/msm/kgsl_drawobj.h +++ b/drivers/gpu/msm/kgsl_drawobj.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2018, 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 @@ -107,6 +107,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) @@ -116,8 +125,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; @@ -126,8 +135,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; }; /** diff --git a/drivers/gpu/msm/kgsl_sync.c b/drivers/gpu/msm/kgsl_sync.c index d484894e06f2..98c117d018e2 100644 --- a/drivers/gpu/msm/kgsl_sync.c +++ b/drivers/gpu/msm/kgsl_sync.c @@ -438,27 +438,54 @@ static void kgsl_sync_fence_callback(struct fence *fence, struct fence_cb *cb) } } -static void kgsl_get_fence_name(struct fence *fence, - char *fence_name, int name_len) +static void kgsl_get_fence_names(struct fence *fence, + struct event_fence_info *info_ptr) { - char *ptr = fence_name; - char *last = fence_name + name_len; + unsigned int num_fences; + struct fence **fences; + struct fence_array *array; + int i; - ptr += snprintf(ptr, last - ptr, "%s %s", - fence->ops->get_driver_name(fence), - fence->ops->get_timeline_name(fence)); - - if ((ptr + 2) >= last) + if (!info_ptr) return; - if (fence->ops->fence_value_str) { - ptr += snprintf(ptr, last - ptr, ": "); - fence->ops->fence_value_str(fence, ptr, last - ptr); + array = to_fence_array(fence); + + if (array != NULL) { + num_fences = array->num_fences; + fences = array->fences; + } else { + num_fences = 1; + fences = &fence; + } + + info_ptr->fences = kcalloc(num_fences, sizeof(struct fence_info), + GFP_ATOMIC); + if (info_ptr->fences == NULL) + return; + + info_ptr->num_fences = num_fences; + + for (i = 0; i < num_fences; i++) { + struct 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 fence *fence; @@ -479,8 +506,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 = fence_add_callback(fence, &kcb->fence_cb, diff --git a/drivers/gpu/msm/kgsl_sync.h b/drivers/gpu/msm/kgsl_sync.h index 6998b40f77eb..a53cd51733ed 100644 --- a/drivers/gpu/msm/kgsl_sync.h +++ b/drivers/gpu/msm/kgsl_sync.h @@ -1,3 +1,4 @@ + /* Copyright (c) 2012-2014,2017-2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify @@ -93,7 +94,7 @@ void kgsl_sync_timeline_put(struct kgsl_sync_timeline *ktimeline); struct kgsl_sync_fence_cb *kgsl_sync_fence_async_wait(int fd, bool (*func)(void *priv), void *priv, - char *fence_name, int name_len); + struct event_fence_info *info_ptr); void kgsl_sync_fence_async_cancel(struct kgsl_sync_fence_cb *kcb); @@ -139,7 +140,7 @@ static inline void kgsl_sync_timeline_put(struct kgsl_sync_timeline *ktimeline) static inline struct kgsl_sync_fence_cb *kgsl_sync_fence_async_wait(int fd, bool (*func)(void *priv), void *priv, - char *fence_name, int name_len) + struct event_fence_info *info_ptr) { return NULL; }