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; }